Closed justinbmeyer closed 7 years ago
MyClassA {
}
MyClassB {
method() {
this.myClassA = new MyClass()
}
}
var b = new MyClassB();
canReflect.onKeyValue(b,"myClassA", function(newValue){
});
b.method()
Person {
get fullName(){ ... }
}
{{person.fullName}} {{person.fullName}}
make sure cycles work
Tests from the erased data
QUnit.test("Should not duplicate proxies #21", function(){
var a = {who: 'a'},
b = {who: 'b'},
c = {who: 'c'}
aproxy = observe(a)
cproxy = observe(c)
aproxy.b = b;
cproxy.b = b;
QUnit.equal(aproxy.b, cproxy.b, "proxied objects should not be duplicated");
});
QUnit.test("Should not duplicate proxies in a cycle #21", function(){
var a = {};
var b = {};
var c = {};
a.b = b;
b.c = c;
c.a = a;
observe(a);
QUnit.equal(c.a, a, "proxied objects should not be duplicated");
});
QUnit.test("Should convert nested objects to observables in a lazy way #21", function(){
var nested = {};
var obj = {nested: nested};
var obs = observe(obj);
QUnit.equal(!!canReflect.isObservableLike(nested), false) //-> nested is not converted yet
QUnit.equal(canReflect.isObservableLike(obs.nested), true) //-> nested is converted to a proxy and the proxy returned
});
QUnit.test("Should convert properties if bound", function() {
var nested = {};
var obj = {};
var obs = observe(obj);
canReflect.getKeyValue(obs, "nested", function(newVal){
QUnit.equal(canReflect.isObservableLike(newVal), true) //-> is a proxied nested
})
obs.nested = nested;
});
QUnit.test("Nested objects should be observables #21", function(){
expect(1);
var obj = {nested: {}, primitive: 2};
var obs = observe(obj);
obs.nested.prop = 1;
canReflect.onKeyValue(obs.nested, "prop", function(newVal){
console.log('hi')
assert.ok(true, "change is triggered on a nested property");
});
var x = obs.nested;
x.prop = "abc";
});
This test passes, but I'm not sure where to put this:
var Component = require("can-component");
var stache = require("can-stache");
var observe = require("can-observe");
QUnit.test('Works with can-observe', function () {
var vm = observe({
firstName: 'Chris',
lastName: 'Gomez',
fullName: function() {
return this.firstName + ' ' + this.lastName;
}
});
Component.extend({
tag: 'can-observe-component',
viewModel: vm,
view: stache('Name: {{fullName}}')
});
var frag = stache('<can-observe-component firstName:bind="firstName" lastName:bind="lastName" />')(vm);
QUnit.equal(frag.firstChild.innerHTML, 'Name: Chris Gomez', 'Rendered fullName');
vm.firstName = 'Justin';
vm.lastName = 'Meyer';
QUnit.equal(frag.firstChild.innerHTML, 'Name: Justin Meyer', 'Rendered fullName after change');
});
This test passes, but I'm not sure where to put this:
Assuming this test also passes with MockComponent, let's break MockComponent out of can-stache-bindings and into can-test-helpers, which would make it available to both.
For historical reference, a more expressive version of the above test is pasted below (it will not be included in the published version):
QUnit.test('Works with can-observe', function () {
var stache = require("can-stache");
var observe = require("can-observe");
var parentVm = observe({
firstName: 'Chris',
lastName: 'Gomez',
});
var childVm = observe({
fullName: function() {
return this.firstName + ' ' + this.lastName;
}
});
Component.extend({
tag: 'can-observe-component',
viewModel: function(initialData) {
Object.keys(initialData).forEach(function(key) {
childVm[key] = initialData[key];
});
return childVm;
},
view: stache('Name: {{fullName}}')
});
var frag = stache('<can-observe-component firstName:bind="firstName" lastName:bind="lastName" />')(parentVm);
QUnit.equal(frag.firstChild.innerHTML, 'Name: Chris Gomez', 'Rendered fullName');
parentVm.firstName = 'Justin';
parentVm.lastName = 'Meyer';
QUnit.equal(frag.firstChild.innerHTML, 'Name: Justin Meyer', 'Rendered fullName after change');
});
- Make sure it works with can-component. Force in can-component?
I'm not in favor of forcing this just yet, because can-component does this one weirdly. If you pass a can-observe in as a viewModel, it's treated as a singleton viewModel (which is correct) but does not receive any properties from initial values of bindings (which is confusing). This means that you have to write a generator function and manually copy props because can-observe isn't a constructor, and so the symmetry that we've had in can-component up to this point (prototype object <-> constructor class) isn't available. Let's get a consensus on how to approach this, and maybe make it official in docs.
class Foo(){
constructor() {
return observe(this);
},
method: function(){
this.prop = "zed";
}
}
can.Component.extend({
ViewModel: Foo
})
can.Component.extend({
ViewModel: function(){
return observe({
method: function(){
this.prop = [1,2,3]
},
pop: function(){
this.prop.pop();
},
get foo() {
}
})
}
})
list.reverse()
... does the page update? (might need to overwrite .reverse()
and others to trigger .list())can-connect
?
[x] - make the proxy version use
onKeyValue
instead ofaddEventListener
(on the proxy object itself instead of the proxied object)[x] - solve the duplicate issue
[x] - make it convert nested values into proxied observables on set. - Don't convert observables
canReflect.isObservable()
[x] - on initialization change all props?
[x] - Make sure it works with
can-component
. Force incan-component
?[x] - convert
getters
into computed properties ?