Meteor: Included templates still use the context of the parent #103

Closed
bminer opened this Issue Nov 19, 2012 · 14 comments

Projects

None yet

3 participants

@bminer
Owner
bminer commented Nov 19, 2012

When you include a template using include "foo.blade" the subtemplate uses the data context of the current template.

@bminer bminer was assigned Nov 19, 2012
@VanCoding

Thanks for creating the issue. I'm so glad you're working on it!

Great work! :)

@bminer bminer added a commit that referenced this issue Dec 19, 2012
@bminer Push to 3.0.0alpha10
Refactored Meteor smart package
Improved Meteor runtime to allow included templates to access their helpers (addresses #103) - Fix not tested
liveui: Added on_invalidate_clean function to Context instead of relying on the function's name to be set. Uglify can mangle function names.
78c5cad
@bminer bminer was assigned Jan 4, 2013
@bminer
Owner
bminer commented Jan 4, 2013

@VanCoding - has this been fixed? Can you confirm? Thanks!

@bminer
Owner
bminer commented Feb 4, 2013

Can someone please confirm that this bug has been fixed? Thanks!

@bminer
Owner
bminer commented Mar 7, 2013

This issue has been fixed. Included templates inherit their parent's locals and view helpers, but they can be overwritten. Issue #141 discusses the possibility of preventing included views from inheriting their parent's locals by default.

@bminer bminer closed this Mar 7, 2013
@defualt
defualt commented Mar 25, 2013

I'm having the following issue:

Within the file parent.blade, there is the following dynamic include:

include dynamicTemplateVaraible exposing someDataVariable

Here, someVariable is not available within the template we assigned to dynamicTemplateVaraible. Instead,
dynamicTemplateVaraible has the same locals as parent.blade.

-=-=-=-==-

However, in non-dynamic includes things behave as expected, as in:

include "nonDynamic.blade" exposing someDataVariable

Here, someDataVariable is available to the included template, and the parent locals are not available to the child.

=======
UPDATE

I found a pretty clean workaround.

Create a dynamicInclude.blade file.
That file should contain only this:
include dynamicIncludeName

Then when you want to use a dynamic include in a parent template, write it like this:
-var dynamicIncludeName = variableDerivedFromLocalOrWhatever;
include 'dynamicInclude' exposing dynamicIncludeName, whateverOtherVariable, anotherVariableEtc

What happens is dynamicInclude.blade will receive the exposed variables and use them as locals, as in this part, it is a static include and static includes do fine with receiving exposed variables. dynamicInclude.blade uses the variable dynamicIncludeName to dynamically include the desired dynamic template. Because this is a dynamic include, exposing variables doesn't work, and it receives the local variables of its parent, and those local variables (whateverOtherVariable,anotherVariableEtc) are the ones we intended to reach the desired dynamic template.

@bminer bminer reopened this Mar 26, 2013
@bminer
Owner
bminer commented Apr 8, 2013

That's some weird behavior... I'll have to track down the issue as time permits. Thanks for the bug report!

@defualt
defualt commented Apr 11, 2013

Looks like my workaround doesn't work in Safari. I'm getting a nasty error:

TypeError: setting a property that has only a getter
at /Users/username/meteortest/groop3/views/characterList.blade:2:1

1 | -var dynamicIncludeName = nestedViewItem.includeName + 'Panel';
2 > include dynamicIncludeName

@bminer
Owner
bminer commented Apr 17, 2013

Could you post the full stack trace, please?

@bminer
Owner
bminer commented Apr 17, 2013

@defualt - I cannot replicate your bug. I believe that this issue is now closed. Try upgrading to the latest version of Blade and Meteor 0.6.2.

@defualt
defualt commented Apr 18, 2013

I've updated and after updating, I've created new meteor/mrt/blade projects to be sure I'm working with the most up to date and the error persists. I think my particular exception is a result of workarounds for some bugs in meteor or blade, but I think the root of the issue is that dynamic includes are not exposing specified variables.

I made this repository to demonstrate the bug. You will find instructions for adding and removing commenting to show meaningful errors if you mrt it.
https://github.com/defualt/bladebug

And this is the project I am working on where you can see the exception in Safari.
https://github.com/defualt/Peanuts

Here is the stack trace from my Peanuts project in safari:

(anonymous function)() at characterListPanel.js:52
(anonymous function)() at deftemplate.js:138
(anonymous function)() at spark.js:846
(anonymous function)() at deps.js:129
(anonymous function)() at deps.js:64
(anonymous function)() at deps.js:255
(anonymous function)() at spark.js:844
(anonymous function)() at deftemplate.js:135
(anonymous function)() at spark.js:1183
(anonymous function)() at deftemplate.js:116
(anonymous function)() at spark.js:1114
(anonymous function)() at deftemplate.js:115
(anonymous function)() at runtime-meteor.js:45
(anonymous function)() at spark.js:1114
(anonymous function)() at runtime-meteor.js:44
anonymous() at characterList.js:15
(anonymous function)() at characterList.js:25
(anonymous function)() at deftemplate.js:138
(anonymous function)() at spark.js:846
(anonymous function)() at deps.js:129
(anonymous function)() at deps.js:64
(anonymous function)() at deps.js:255
(anonymous function)() at spark.js:844
(anonymous function)() at deftemplate.js:135
(anonymous function)() at spark.js:1183
(anonymous function)() at deftemplate.js:116
(anonymous function)() at spark.js:1114
(anonymous function)() at deftemplate.js:115
(anonymous function)() at runtime-meteor.js:45
(anonymous function)() at spark.js:1114
(anonymous function)() at runtime-meteor.js:44
anonymous() at dynamicInclude.js:15
(anonymous function)() at dynamicInclude.js:25
(anonymous function)() at deftemplate.js:138
(anonymous function)() at spark.js:846
(anonymous function)() at deps.js:129
(anonymous function)() at deps.js:64
(anonymous function)() at deps.js:255
(anonymous function)() at spark.js:844
(anonymous function)() at deftemplate.js:135
(anonymous function)() at spark.js:1183
(anonymous function)() at deftemplate.js:116
(anonymous function)() at spark.js:1114
(anonymous function)() at deftemplate.js:115
(anonymous function)() at runtime-meteor.js:45
(anonymous function)() at spark.js:1114
(anonymous function)() at runtime-meteor.js:44
(anonymous function)() at rootView.js:39
(anonymous function)() at runtime.js:512
wrapper() at runtime.js:462isolateWrapper() at runtime.js:467
(anonymous function)() at runtime.js:510
(anonymous function)() at spark.js:1114
itemFuncWrapper() at runtime.js:509
(anonymous function)() at runtime.js:533
anonymous() at rootView.js:31
(anonymous function)() at rootView.js:57
(anonymous function)() at deftemplate.js:138
(anonymous function)() at spark.js:846
(anonymous function)() at deps.js:129
(anonymous function)() at deps.js:64
(anonymous function)() at deps.js:255
(anonymous function)() at spark.js:844
(anonymous function)() at deftemplate.js:135
(anonymous function)() at spark.js:1183
(anonymous function)() at deftemplate.js:116
(anonymous function)() at spark.js:1114
(anonymous function)() at deftemplate.js:115
(anonymous function)() at peanuts.js:17
(anonymous function)() at spark.js:846
(anonymous function)() at deps.js:129
(anonymous function)() at deps.js:64
(anonymous function)() at deps.js:255
(anonymous function)() at spark.js:844
(anonymous function)() at convenience.js:3
(anonymous function)() at spark.js:39
(anonymous function)() at spark.js:211
(anonymous function)() at spark.js:411
(anonymous function)() at convenience.js:2
(anonymous function)() at peanuts.js:14
(anonymous function)() at bladestest.js:230
(anonymous function)() at bladestest.js:229
(anonymous function)() at startup_client.js:8

Finally, the Blade documentation about includes is somewhat misleading. Notice that you are expressing a global variable , which you are then exposing to a child template.

- header = "Header: 1, 2, 3"

  • text = "This is some text: 1, 2, 3"
  • for(var i = 0; i < 10; i++)
       include "foobar" exposing i, text

"text" is available in the included template and everywhere else because it's global. In this example, you are including "foobar.blade" non-dynamically. If you were to include it dynamically, and if you expressed "text" with a "var" keyword, then "text" would not be available to the child. This tripped me up while trying to figure out this bug because I used this as an example and it appeared that my dynamic include/exposing was working, but this was only because the global variable was making it into my child template due to it's being global, not due its being exposed.

Thanks for your work on this.

@bminer
Owner
bminer commented Apr 23, 2013

@defualt - I can now duplicate your bug, and you are correct. I will correct this shortly.

@bminer bminer added a commit that closed this issue Apr 23, 2013
@bminer Push to 3.2.4
Including a dynamic filename now works with identifiers and Object properties (closes #158)
Previously, including a file with a dynamic filename prevented "exposing" keyword from doing its job. This has now been fixed. (fixes #103)
Added new tests
756e599
@bminer bminer closed this in 756e599 Apr 23, 2013
@defualt
defualt commented Apr 28, 2013

Since updating, variables will only be passed into an included template if you use "exposing". If you omit "exposing [variables]" then no local variables get passed into the included template.

This behavior does not match the documentation.
"By default, Blade will pass the parent's local variables to the included template; however, when using the exposing keyword, you can specify exactly which variables are to be exposed to the included template."

I've updated https://github.com/defualt/bladebug to demonstrate the issue.


Also, I can confirm that exposing variables in a dynamic include effectively passes those variables into the included template. So now dynamic and non-dynamic includes that use "exposing" function as expected.

@bminer
Owner
bminer commented Apr 29, 2013

Sorry, @defualt - I should clarify the documentation. Blade will pass view locals to included (child) templates. It will not automatically pass local variables declared using the var keyword. It only passes the properties of the locals Object.

@bminer bminer added a commit that referenced this issue Apr 29, 2013
@bminer Clarified README documentation (addresses issue #103)
Enhanced test suite
44867e7
@bminer
Owner
bminer commented Apr 29, 2013

@defualt - Thank you very much for your help. I believe that the documentation and the implementation should now be consistent with one another. If not, please feel free to post back here.

Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment