is there a multiline helper syntax? (for ex, for contextual components and yield)
kjhangiani opened this issue · comments
With the addition of contextual components, and the component
and hash
helpers in ember 2.3+, we've started to move some older code to use the new syntax.
However, it's somewhat tedious to yield
large blocks of components using the hash
helper without the ability to do multiline components.
Is there a supported way, or plan to allow this in emblem?
For ex, currently we use this syntax a lot:
= wijmo/toolbar/buttons/text-strikethrough [
_firstSelectedCellStylingObservable=(readonly _firstSelectedCellStylingObservable)
isReadonly=(readonly isReadonly)
buttonAction=(action applyStyles)
]
however, when changing to yield with contextual components, we end up with lines like:
yield (hash (textStrikethrough=(component "wijmo/toolbar/buttons/text-strikethrough" isReadonly=isReadonly buttonAction=(action applyStyles)) textBold=(component "wijmo/toolbar/buttons/text-bold" isReadonly=isReadonly buttonAction=(action applyStyles)))
etc etc which is far less readable. Is there any way to make this more palatable in emblem?
So - discovered that this syntax successfully compiles:
yield (hash buttons=(hash saveSheet=(component "wijmo/toolbar/buttons/save-sheet" [
isReadonly=isReadonly
buttonAction=(action saveComponent)
]) fontFamily=(component "wijmo/toolbar/buttons/font-family" [
_firstSelectedCellStylingObservable=(readonly _firstSelectedCellStylingObservable)
_closeMenuRequestedObservable=(readonly _closeMenuRequestedObservable)
_closeMenuException=(readonly _closeMenuException)
closeAllMenus=(action closeAllMenus)
isReadonly=(readonly isReadonly)
buttonAction=(action applyStyles)
])))
and actually yields the components - however, the assignments inside the bracket do not work (they remain undefined) - so it's not usable. Still trying various combinations to see if there's any way to get linebreaks into the syntax
Not the most elegant solution, but this does work:
= yield-hash [
class="spreadsheet-toolbar"
saveSheet=(component "wijmo/toolbar/buttons/save-sheet" isReadonly=(readonly isReadonly) buttonAction=(action saveComponent))
fontFamily=(component "wijmo/toolbar/buttons/font-family" isReadonly=(readonly isReadonly) buttonAction=(action applyStyles))
] as |toolbar|
yield (hash saveSheet=toolbar.saveSheet fontFamily=toolbar.fontFamily)
where the yield-hash
component just does yield this
in its template. This works, and probably has an extremely negligible performance impact, but does make the code far more readable.
very good point! we have some components that are also starting to get a bit messy like this.
what do you think an ideal syntax in Emblem would look like?
honestly - I'm open to anything - as long as there is a way to do it! I do like the [ ... ]
syntax for components, perhaps it can just be the de-facto way to do multiline in emblem? Though the indenting might get tricky. some initial thoughts...
yield (hash buttons=(hash [
saveSheet=(component 'save-sheet' [
isReadonly=isReadonly
buttonAction=(action saveComponent)
])
fontFamily=(component 'font-family' [
isReadonly=isReadonly
buttonAction=(action applyStyles)
])
]))
Another possibility is to use something like double brackets [[
and ]]
and just replace everything between [[
]]
onto the same line - so that the indenting can be done as a style preference but actually wouldn't affect parsing (this might make it easier to manage deeply nested helpers - which does happen on occasion)
ie:
yield (hash buttons=(hash [[
saveSheet=(component 'save-sheet' [[
isReadonly=isReadonly
buttonAction=(action saveComponent)
]])
fontFamily=(component 'font-family' [[
isReadonly=isReadonly
buttonAction=(action applyStyles)
]])
]]))
Or a prefix on each line to indicate it should be brought up to the previous line kind of like the '
operator (not as much a fan of this one)
I've also only thought of the yield case here - but helpers can be used inline in htmlbars, in component assignments, etc, so there are considerations there too.
I like your first case, it seems in line with the current bracket syntax and would only require a small expansion of the current bracket rules (e.g they can now apply to subexpressions). So:
(<keyword [
.. ])
Would it be worth limiting keyword
to only component
or hash
, or any subexpression? Would this cover the use cases you are currently facing?
This would definitely cover the use case we are currently experiencing - would it work in the nested form as well? We sometimes use a hash with several sub hashes to further organize the contextual components. Though honestly those are easy refactors, so even in the non-nested case its useful.
Initially was thinking it should work for all helpers, but on second thought, it should probably be limited to component
and hash
. Those are the only helpers that use the attr=value
syntax inside the helper, I believe? other helpers are (helper-name arg1 arg2)
which doesn't fit within the current [...]
model.
As far as I know there's no way to create a custom helper that supports arg=value
.
for the component case, would it be:
(component '/path/to/component' [
arg1=value1
arg2=value2
])
or
(component [
'/path/to/component'
arg1=value1
arg2=value2
])
(component
has the unique first parameter before the arg=value
params that dictates the component path). I would say if I had the choice, the former should be the only supported way.
Yeah, I think it would be ideal to allow in nested subexpressions.
I think queryParams
is another subexpression helper that takes key / value pairs, though probably isn't one that would benefit as much as hash
or component
. At the same time, if you had something like (my-helper a b c d e f g)
I don't know if it would be very much different for Emblem to allow brackets there as well:
(my-helper [
a
b
c
d
e
])
@thec0keman awesome!