Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Template scope variables are not passed to the include template #54

Open
antpaw opened this issue Aug 12, 2016 · 14 comments
Open

Comments

@antpaw
Copy link

antpaw commented Aug 12, 2016

In this example you would expect that myScopedVar is available in low_level_template.pug.

for myScopedVar in [1, 2, 3] 
  include low_level_template

But it's not. That's a huge deal for me because that's how it works in your node module used for expressjs. That's also how most people assume it should work 1 2. Also that's how jadeify does it.

Here is a testcase example (please follow the steps from readme.md) and watch the browser console output. The problem that the isomorphic_template gets compiled with this line:

for (var pug_index0 = 0, pug_length0 = pug_obj0.length; pug_index0 < pug_length0; pug_index0++) {
   var myScopedVar = pug_obj0[pug_index0];

   pug_html = pug_html + (null == (pug_interp = __webpack_require__(9).call(this, locals)) ? "" : pug_interp);
}

it's clear to see that myScopedVar is set but not provided to the module 9 (which is the low_level_template.pug file). Jadeify would "inline" this template so the var scope is still present.

@antpaw
Copy link
Author

antpaw commented Aug 14, 2016

I've found this answer #47 I strongly disagree with this idea.

This is a important template feature and using locals is not documented in any way in pug/jade documentation. Setting something on a global object locals will always lead to side effects that might cause unexpected behaviour. It might be not a big deal for client side, but in a isomorphic app where partials have to work on node as well you might be modifying unintentionally object references for different requests.

The best fix for this would be if pug had two different syntaxes for include that let programmers decide to inline or to require the template. Or a syntax that provides a way to define variables that should be passed down to the include along with already set variables.

Chances for this to happen are almost zero i would say, so I suggest that the library should inline every "include".

@TimothyGu
Copy link
Member

I guess @sokra (who initially implemented template inlining) didn't realize this incompatibility. I agree with your evaluation, and I'm okay with the idea of adding a require plugin in pug-loader. But until such a keyword is implemented, I'm inclined to keep the status quo as it is, so that existing Jade (and jade-loader) users can more easily upgrade to Pug.

@ryoikarashi
Copy link

any update?

@antpaw
Copy link
Author

antpaw commented Apr 28, 2017

@ryoikarashi you can use my fork for now https://github.com/antpaw/pug-loader

@forbaz
Copy link

forbaz commented May 23, 2017

Hello everyone.
I don't know why this happen, but if in included file we call any mixin variables that we passed returned their value.
For example:

//- empty.pug
mixin empty()
  if false
    p nothing here
//- template1.pug
include empty.pug
for myScopedVar in [1, 2, 3]
  include low_level_template
//- low_level_template.pug
+empty()
p= myScopedVar

And this work. But if we just delete line with +empty() mixin call, myScopedVar return undefined.
Maybe this can help someone.

@damassi
Copy link

damassi commented Dec 23, 2017

@TimothyGu - Any tips as to how to go about implementing this would be appreciated. This issue just put a hard stop on our large webpack refactor

@antpaw
Copy link
Author

antpaw commented Dec 23, 2017

@damassi this is the fork i have used to transfer my ezel based setup to webpack. The only downside I can see is that the bundle size will get bigger (extremely bigger, in extrem cases), but it uses the same convention as the browserify compiler ect, so coming from other compilers should not cause noticeable size difference. But it could be done more efficient if you would somehow "collect" all the variable form the closer scope and pass them to the included template function instead of inlining it. I think this will require a major change in the internal workings of pug, and am not even sure if the "collecting" part is possible.

@damassi
Copy link

damassi commented Dec 23, 2017

Thanks @antpaw - will look into it!

@damassi
Copy link

damassi commented Jan 4, 2018

@antpaw - Can confirm your fork fixed the issue. Thanks again 👍

@DevanB
Copy link

DevanB commented May 18, 2018

Any movement on getting this fixed?

@AmirTugi
Copy link

AmirTugi commented Jul 21, 2018

For those of you who seek a hack for the for loop - the solution in #47 works if you define the var in the locals:

- locals namesArray = ['Amir', 'Tugi']
- each element in locals.namesArray
    - locals.element = element
    include path/to/file // <-- The file will now be able to access the variable via #{element}

With that said, any progress on the real official solution yet?

@CharlesGouldmann
Copy link

CharlesGouldmann commented Nov 27, 2019

Any progress on this?

For now I will use @antpaw 's fork which seems to work great.

@titantwentyone
Copy link

It would be great if the docs could be updated to relfect this. Took me a while to figure out what was happening here. @AmirTugi's fix worked perfectly for me.

@webdiscus
Copy link

Following simple example work with the pug-loader:

- var items = ['Hello', 'pug!']
each str in items
  include ./include-var-str

file include-var-str.pug:

i= str

The local variable str defined in each in cycle is available in included template.

Output:

<i>Hello</i><i>pug!</i>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants