#255421: A change to @Model property needs to be reported to knockout.js unless it is the same reference.
authorJaroslav Tulach <jtulach@netbeans.org>
Sat, 19 Sep 2015 15:05:59 +0200
changeset 990581f50820e5e
parent 989 af449e1eaedc
child 991 a5c83b735cca
#255421: A change to @Model property needs to be reported to knockout.js unless it is the same reference.
json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java
json/src/main/java/org/netbeans/html/json/impl/ModelProcessor.java
json/src/test/java/org/netbeans/html/json/impl/DeepChangeTest.java
     1.1 --- a/json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java	Fri Sep 18 10:42:15 2015 +0200
     1.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java	Sat Sep 19 15:05:59 2015 +0200
     1.3 @@ -305,6 +305,33 @@
     1.4          
     1.5          Utils.exposeHTML(KnockoutTest.class, "");
     1.6      }
     1.7 +
     1.8 +    @KOTest public void nestedObjectEqualsChange() throws Exception {
     1.9 +        nestedObjectEqualsChange(true);
    1.10 +    }
    1.11 +
    1.12 +    @KOTest public void nestedObjectChange() throws Exception {
    1.13 +        nestedObjectEqualsChange(false);
    1.14 +    }
    1.15 +    private  void nestedObjectEqualsChange(boolean preApply) throws Exception {
    1.16 +        Utils.exposeHTML(KnockoutTest.class,
    1.17 +"            <div data-bind='with: archetype'>\n" +
    1.18 +"                <input id='input' data-bind='value: groupId'></input>\n" +
    1.19 +"            </div>\n"
    1.20 +        );
    1.21 +
    1.22 +        js = Models.bind(new KnockoutModel(), newContext());
    1.23 +        if (preApply) {
    1.24 +            js.applyBindings();
    1.25 +        }
    1.26 +        js.setArchetype(new ArchetypeData());
    1.27 +        js.getArchetype().setGroupId("org.netbeans.html");
    1.28 +        js.applyBindings();
    1.29 +
    1.30 +        String v = getSetInput("input", null);
    1.31 +        assertEquals("org.netbeans.html", v, "groupId has been changed");
    1.32 +        Utils.exposeHTML(KnockoutTest.class, "");
    1.33 +    }
    1.34      
    1.35      @KOTest public void modifyValueAssertAsyncChangeInModel() throws Exception {
    1.36          if (js == null) {
     2.1 --- a/json/src/main/java/org/netbeans/html/json/impl/ModelProcessor.java	Fri Sep 18 10:42:15 2015 +0200
     2.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/ModelProcessor.java	Sat Sep 19 15:05:59 2015 +0200
     2.3 @@ -589,10 +589,10 @@
     2.4                  w.write("    proto.verifyUnlocked();\n");
     2.5                  w.write("    Object o = prop_" + p.name() + ";\n");
     2.6                  if (isModel[0]) {
     2.7 +                    w.write("    if (o == v) return;\n");
     2.8                      w.write("    prop_" + p.name() + " = v;\n");
     2.9 +                } else {
    2.10                      w.write("    if (TYPE.isSame(o , v)) return;\n");
    2.11 -                } else {
    2.12 -                    w.write("    if (TYPE.isSame(prop_" + p.name() + ", v)) return;\n");
    2.13                      w.write("    prop_" + p.name() + " = v;\n");
    2.14                  }
    2.15                  w.write("    proto.valueHasMutated(\"" + p.name() + "\", o, v);\n");
     3.1 --- a/json/src/test/java/org/netbeans/html/json/impl/DeepChangeTest.java	Fri Sep 18 10:42:15 2015 +0200
     3.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/DeepChangeTest.java	Sat Sep 19 15:05:59 2015 +0200
     3.3 @@ -92,11 +92,19 @@
     3.4          }
     3.5          @ComputedProperty
     3.6          static String sndName(MyY one) {
     3.7 -            return one.getValue().toUpperCase();
     3.8 +            if (one == null || one.getValue() == null) {
     3.9 +                return null;
    3.10 +            } else {
    3.11 +                return one.getValue().toUpperCase();
    3.12 +            }
    3.13          }
    3.14          @ComputedProperty @Transitive(deep = false) 
    3.15          static String noName(MyY one) {
    3.16 -            return one.getValue().toUpperCase();
    3.17 +            if (one == null || one.getValue() == null) {
    3.18 +                return null;
    3.19 +            } else {
    3.20 +                return one.getValue().toUpperCase();
    3.21 +            }
    3.22          }
    3.23          @ComputedProperty @Transitive(deep = true) 
    3.24          static String thrdName(MyY one) {
    3.25 @@ -450,6 +458,28 @@
    3.26      }
    3.27  
    3.28      @Test
    3.29 +    public void rebindReplacesTheInstanceAndNotifies() throws Exception {
    3.30 +        BrwsrCtx ctx = Contexts.newBuilder().build();
    3.31 +        final MyY one = Models.bind(new MyY(), ctx);
    3.32 +        MyX p = Models.bind(
    3.33 +            new MyX(one, new MyY("Hi", 333), new MyY("Hello", 999)), c
    3.34 +        ).applyBindings();
    3.35 +
    3.36 +        Map m = (Map) Models.toRaw(p);
    3.37 +        
    3.38 +        Object v = m.get("one");
    3.39 +        assertNotNull(v, "Value should be in the map");
    3.40 +        One o = (One) v;
    3.41 +        assertEquals(o.changes, 0, "No changes yet");
    3.42 +
    3.43 +        MyY y = Models.bind(new MyY(), ctx);
    3.44 +        p.setOne(y);
    3.45 +
    3.46 +        assertSame(p.getOne(), y);
    3.47 +        assertSame(o.changes, 1, "One change now");
    3.48 +    }
    3.49 +
    3.50 +    @Test
    3.51      public void mixingWithCloneIsOK() throws Exception {
    3.52          BrwsrCtx ctx = Contexts.newBuilder().build();
    3.53          final MyY one = Models.bind(new MyY("Ahoj", 0), ctx);