diff --git a/packages/test-in-browser/driver.html b/packages/test-in-browser/driver.html
index 3032ad799b..4b27177fa5 100644
--- a/packages/test-in-browser/driver.html
+++ b/packages/test-in-browser/driver.html
@@ -88,7 +88,7 @@
{{#each testdata}}
- {{> test_group ThisWithDep}}
+ {{> test_group thisWithDep}}
{{/each}}
@@ -98,10 +98,10 @@
{{#each tests}}
- {{> test ThisWithDep}}
+ {{> test thisWithDep}}
{{/each}}
{{#each groups}}
- {{> test_group}}
+ {{> test_group thisWithDep}}
{{/each}}
diff --git a/packages/test-in-browser/driver.js b/packages/test-in-browser/driver.js
index 83293e8801..bbc4d5efca 100644
--- a/packages/test-in-browser/driver.js
+++ b/packages/test-in-browser/driver.js
@@ -344,12 +344,20 @@ Template.testTable.helpers({
testdata: function () {
topLevelGroupsDep.depend();
return resultTree;
- }
+ },
+ thisWithDep: function () {
+ this.dep.depend();
+ return this;
+ },
});
//// Template - test_group
-Template.test_group.helpers({
+Template.test_group.events({
+ thisWithDep: function () {
+ this.dep.depend();
+ return this;
+ },
'click .groupname': function (evt) {
changeToPath(this.path);
// prevent enclosing groups from also triggering on
@@ -494,13 +502,3 @@ Template.event.helpers({
return !!this.cookie;
}
});
-
-
-// XXX BAD
-// This is the only way we can currently write a helper
-// that gets the current data context inside an #each --
-// make it global. D'oh.
-window.ThisWithDep = function () {
- this.dep.depend();
- return this;
-};
diff --git a/packages/test-in-browser/package.js b/packages/test-in-browser/package.js
index de3c1b6d5f..6c293441e2 100644
--- a/packages/test-in-browser/package.js
+++ b/packages/test-in-browser/package.js
@@ -4,7 +4,6 @@ Package.describe({
});
Package.on_use(function (api) {
-
// XXX this should go away, and there should be a clean interface
// that tinytest and the driver both implement?
api.use('tinytest');
diff --git a/packages/ui/base.js b/packages/ui/base.js
index aca1619598..623b86f7e9 100644
--- a/packages/ui/base.js
+++ b/packages/ui/base.js
@@ -115,7 +115,6 @@ _extend(UI.Component, {
// pretty-print correctly.
kind: "Component",
guid: "1",
- data: null,
dom: null,
// Has this Component ever been inited?
isInited: false,
diff --git a/packages/ui/dombackend.js b/packages/ui/dombackend.js
index 3185bf13f3..d963dd9255 100644
--- a/packages/ui/dombackend.js
+++ b/packages/ui/dombackend.js
@@ -29,7 +29,7 @@ if (Meteor.isClient) {
// jQuery does fancy stuff like creating an appropriate
// container element and setting innerHTML on it, as well
// as working around various IE quirks.
- return jQuery.parseHTML(html);
+ return jQuery.parseHTML(html) || [];
},
// `selector` is non-null. `type` is one type (but
// may be in backend-specific form, e.g. have namespaces).
diff --git a/packages/ui/fields.js b/packages/ui/fields.js
index bb8ed11dd4..3dc67f9930 100644
--- a/packages/ui/fields.js
+++ b/packages/ui/fields.js
@@ -35,7 +35,7 @@ _extend(UI.Component, {
} else if ((comp = findComponentWithProp(id, self))) {
// found a method
result = comp[id];
- thisToBind = self;
+ thisToBind = getData(self);
} else if (id === 'if') {
result = UI.If;
} else if (id === 'each') {
diff --git a/packages/ui/render.js b/packages/ui/render.js
index cd10a88e97..a0cb46e5e6 100644
--- a/packages/ui/render.js
+++ b/packages/ui/render.js
@@ -21,8 +21,16 @@ UI.renderToRange = function (kind, props, range, parentComp) {
// XXX Handle case where kind is function reactively.
// Reuse the same DomRange.
- if ((typeof kind) === 'function')
- kind = kind();
+ if ((typeof kind) === 'function') {
+ // XXX scope this autorun
+ Deps.autorun(function (c) {
+ if (c.firstRun) {
+ kind = kind();
+ } else {
+ debugger; // XXX
+ }
+ });
+ }
if (kind === null)
return null;
@@ -42,9 +50,15 @@ UI.renderToRange = function (kind, props, range, parentComp) {
comp.init();
if (comp.render) {
- var buf = makeRenderBuffer();
- comp.render(buf);
- buf.build(comp);
+ // XXX scope this autorun
+ Deps.autorun(function (c) {
+ if (! c.firstRun) {
+ range.removeAll();
+ }
+ var buf = makeRenderBuffer();
+ comp.render(buf);
+ buf.build(comp);
+ });
}
// XXX think about this callback's semantics
@@ -212,20 +226,7 @@ makeRenderBuffer = function (options) {
var start = range.startNode();
var nextNode = start.nextSibling;
// jQuery does fancy html-to-DOM compat stuff here:
- $(start).after(html);
- // now the DOM elements are physically inside the DomRange,
- // but they haven't been added yet (so they aren't tracked
- // and UI hooks haven't been called; they are foreign
- // matter).
- //
- // XXX weirdly, as we add them to the range they are
- // moved to the end, which works out fine unless an
- // exception stops us in the middle, in which case
- // it may look weird to the developer that the order is
- // wrong. Before fixing this (i.e. making it less weird,
- // and maybe less costly), figure out if we should be
- // rendering offscreen via performance testing.
- var lastNode = nextNode.previousSibling;
+ var newNodes = UI.DomBackend.parseHTML(html);
var wire = function (n) {
// returns what ended up in the place of `n`:
@@ -293,16 +294,11 @@ makeRenderBuffer = function (options) {
};
// top level
- for (var n = start.nextSibling, m;
- n; n = (n === lastNode ? null : m)) {
- m = n.nextSibling;
+ for (var i = 0; i < newNodes.length; i++) {
+ var n = newNodes[i];
var result = wire(n);
// `result` is DOM node, component, or null
if (result) {
- if (result.dom)
- // XXX won't be necessary when DomRange takes
- // components in:
- result = result.dom;
range.add(result);
if (result.nodeType === 1 && result.firstChild)
walk(result);