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
Scoped Mixins #1288
Comments
You could actually write mixins that behaved exactly like this as it stands, a little bit tricky I admit: - var listType
mixin list
- listType = 'list'
ul(attributes=attributes)
block
mixin carousel
- listType = 'carousel'
.carousel(attributes=attributes)
.carousel-inner
block
mixin item
case listType
when 'list'
li(attributes=attributes)
block
when 'carousel'
.item(attributes=attributes)
block |
Thanks @ForbesLindesay - that at least gives me a temporary solution/plan b. Do not mind having to create a PR for this if the consensus is that nested mixins should be allowed - what are the jade dev's feelings about allowing this? |
I'm not sure, there's a more general problem here. As it stands, blocks run in the scope in which they are defined, rather than the scope in which they are used. To demonstrate: mixin foo()
- var x = 10
block
- var x = 20
+foo()
= x In the above example, we get 20 not 10. Some people have expressed a desire to have the ability to expose variables into the block. e.g. @jinhuatang in #1012: mixin list(items) //- a list shell
ul
each item in items
li
block(link=link)
mixin link_list(links)
+list(links)
a(href=link.href)= link.text
mixin image_list(links)
+list(links)
img(src=link.src)
= link.text The goal here is very similar. What we're after is an explicit way to expose certain things to the body of a mixin. If we can find a nice way to do this, I'm all for it. At the moment I haven't come up with a nice way to express this intent in the code, or a nice way to implement it in the compiler. |
Can see the problem and thanks for the detailed response. Compiler aspects aside (haven't popped the hood of Jade yet) I have gotten used to passing attributes and attributes=attributes, so could a similar system be used for scope? Using the example from issue #1012 it is possible to use a global variable to make up for a lack of scope: - var _scopedCurrentItem = null
mixin list()
if attributes.items
ul
each item in attributes.items
- _scopedCurrentItem = item
li
block(attributes=attributes)
- _scopedCurrentItem = null
mixin link_list()
+list(attributes=attributes)
a(href=_scopedCurrentItem.href)= _scopedCurrentItem.text
mixin image_list()
+list(attributes=attributes)
img(src=_scopedCurrentItem.src)
= _scopedCurrentItem.text
- var myLinks = [ {href: 'https://www.google.co.uk', src: 'https://www.google.co.uk/images/srpr/logo11w.png', text: 'Google'}, {href: 'https://github.com', src: 'https://github.global.ssl.fastly.net/images/modules/logos_page/Octocat.png', text: 'GitHub'}]
+image_list()(items=myLinks)
+link_list()(items=myLinks) If I could just pass the scope object (holding all variables available at the time) the syntax would look like: mixin list()
if attributes.items
ul
each item in attributes.items
li
//- Specify scope here so that block gets access to the item variable
block(attributes=attributes, scope=scope)
mixin link_list()
//- Specify scope here so that any local variables are passed to list (e.g. items if not using attributes)
+list(attributes=attributes, scope=scope)
a(href=item.href)= item.text
mixin image_list()
//- Specify scope here so that any local variables are passed to list (e.g. items if not using attributes)
+list(attributes=attributes, scope=scope)
img(src=item.src)
= item.text
- var myLinks = [ {href: 'https://www.google.co.uk', src: 'https://www.google.co.uk/images/srpr/logo11w.png', text: 'Google'}, {href: 'https://github.com', src: 'https://github.global.ssl.fastly.net/images/modules/logos_page/Octocat.png', text: 'GitHub'}]
+image_list()(items=myLinks)
+link_list()(items=myLinks) or if you prefer a more explicit version mixin list(items)
if items
ul
each item in items
- scope.item = item
li
//- Specify scope here so that block gets access to the item variable
block(scope=scope)
mixin link_list(items)
+list(items)
a(href=scope.item.href)= scope.item.text
mixin image_list(items)
+list(items)
img(src=scope.item.src)
= scope.item.text
- var myLinks = [ {href: 'https://www.google.co.uk', src: 'https://www.google.co.uk/images/srpr/logo11w.png', text: 'Google'}, {href: 'https://github.com', src: 'https://github.global.ssl.fastly.net/images/modules/logos_page/Octocat.png', text: 'GitHub'}]
+image_list()(items=myLinks)
+link_list()(items=myLinks) For my use case - all mixins defined within a mixin should be available when you are in the parent mixin. At the minute nested mixins are not available to call following a parent mixin's declaration. There would be no need to pass a scope variable, like with the first example. |
It would be useful if mixins could be scoped/nested so that a parent mixin can determine child behaviour. For instance
whereby list and carousel treat the use of the item mixin differently due to the declaration being scoped inside the parent.
The text was updated successfully, but these errors were encountered: