Skip to content

Commit

Permalink
add support for automatically linking data roots of ractive instances…
Browse files Browse the repository at this point in the history
… from any model
  • Loading branch information
evs-chris committed Jan 25, 2019
1 parent 3c34b67 commit 44f27ce
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 2 deletions.
14 changes: 13 additions & 1 deletion src/model/Model.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import ModelBase, { maybeBind, shuffle } from './ModelBase';
import ModelBase, { checkDataLink, maybeBind, shuffle } from './ModelBase';
import LinkModel from './LinkModel'; // eslint-disable-line no-unused-vars
import getComputationSignature from 'src/Ractive/helpers/getComputationSignature';
import { capture } from 'src/global/capture';
Expand Down Expand Up @@ -146,6 +146,8 @@ export default class Model extends ModelBase {
this.adapt();
}

if (this.dataModel) checkDataLink(this, value);

// keep track of array stuff
if (isArray(value)) {
this.length = value.length;
Expand Down Expand Up @@ -236,6 +238,14 @@ export default class Model extends ModelBase {
child = new Model(this, key);
this.children.push(child);
this.childByKey[key] = child;

if (key === 'data') {
const val = this.retrieve();
if (val && val.viewmodel && val.viewmodel.isRoot) {
child.link(val.viewmodel, 'data');
this.dataModel = val;
}
}
}

if (child._link && (!opts || opts.lastLink !== false)) return child._link;
Expand All @@ -249,6 +259,8 @@ export default class Model extends ModelBase {
const old = this.value;
const value = this.retrieve();

if (this.dataModel) checkDataLink(this, value);

if (force || !isEqual(value, old)) {
this.value = value;
if (this.boundValue) this.boundValue = null;
Expand Down
16 changes: 15 additions & 1 deletion src/model/ModelBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,10 @@ export default class ModelBase {
i = this.children.length;
while (i--) {
const child = this.children[i];
child.rebind(next ? next.joinKey(child.key) : undefined, child, safe);
child.rebind(next ? next.joinKey(child.key) : undefined, child._link || child, safe);
if (this.dataModel) {
this.addShuffleTask(() => checkDataLink(this, this.retrieve()), 'early');
}
}

i = this.bindings.length;
Expand Down Expand Up @@ -358,3 +361,14 @@ export function shuffle(model, newIndices, link, unsafe) {

model.shuffling = false;
}

export function checkDataLink(model, value) {
if (model.dataModel && value !== model.dataModel) {
if (value && value.viewmodel && value.viewmodel.isRoot) {
model.childByKey.data.link(value.viewmodel, 'data');
model.dataModel = value;
} else {
model.childByKey.data.unlink();
}
}
}
39 changes: 39 additions & 0 deletions tests/browser/references.js
Original file line number Diff line number Diff line change
Expand Up @@ -779,4 +779,43 @@ export default function() {

t.strictEqual(r.getContext('.bar').get('@macro.foo.bar.baz'), 42);
});

test(`joining instance data grabs the viewmodel of the instance`, t => {
const c1 = new Ractive({ data: { what: 42 } });
const c2 = new Ractive({ data: { what: 99 } });

const r = new Ractive({
target: fixture,
template: '{{child.data.what}}',
data: { child: c1 }
});

t.equal(fixture.innerHTML, '42');

r.set('child', c2);
t.equal(fixture.innerHTML, '99');
});

test(`automatic linking of instance data in an each`, t => {
const c1 = new Ractive({ data: { what: 42 } });
const c2 = new Ractive({ data: { what: 99 } });
const c3 = new Ractive({ data: { what: 2 } });

const r = new Ractive({
target: fixture,
template: '{{#each children}}{{.data.what}}|{{/each}}',
data: { children: [c1, c2] }
});

t.equal(fixture.innerHTML, '42|99|');

r.shift('children');
t.equal(fixture.innerHTML, '99|');

r.push('children', c1);
t.equal(fixture.innerHTML, '99|42|');

r.unshift('children', c3);
t.equal(fixture.innerHTML, '2|99|42|');
});
}

0 comments on commit 44f27ce

Please sign in to comment.