Reputation: 11755
I have a template that has some repetition in it and am wondering if there's a good way in Ember/Handlebars to handle this situation to decrease the amount of repeat code.
{{#if this.isClickable}}
<button {{on "click" this.onClick}} >
<span>
{{#if this.useText1}}
Text 1
{{else}}
Text 2
{{/if}
<span>
<img src=someIcon />
</button>
{{else}}
<div>
<span>
{{#if this.useText1}}
Text 1
{{else}}
Text 2
{{/if}
<span>
<img src=someIcon />
</div>
{{/if}}
I thought of creating a variable for the text to use and that would shorten my code a bit
{{#if this.isClickable}}
<button {{on "click" this.onClick}} >
<span>
{{this.textToUse}}
<span>
<img src=someIcon />
</button>
{{else}}
<div>
<span>
{{this.textToUse}}
<span>
<img src=someIcon />
</div>
{{/if}}
Is there a way to create variables in the hbs file to assign so I can dynamically create a button or a div rather than if statements that wrap repeated code? Also, would like to avoid creating new components if possible:
Ex:
<ButtonOrDiv clickAction={{onClick}}>
<span>
{{this.textToUse}}
<span>
<img src=someIcon />
</ButtonOrDiv>
Maybe something like:
{{#let
(if this.isClickable 'button' 'div')
(hash
onClick=this.onClick
)
as | Component options |
}}
<Component {{...options}} />
{{/let}}
Upvotes: 0
Views: 116
Reputation: 65173
There are a few options,
this approach assumes your component already has a backing class and offers the (which enables your second snippet)
export default class MyComponet extends Component {
get textToUse() {
return this.useText1 ? 'Text 1' : 'Text 2';
}
// ...
}
{{#if this.isClickable}}
<button {{on "click" this.onRepostsTotalClickAction}} >
<span>
{{this.textToUse}}
<span>
<img src=someIcon />
</button>
{{else}}
<div>
<span>
{{this.textToUse}}
<span>
<img src=someIcon />
</div>
{{/if}}
Docs: https://guides.emberjs.com/release/components/component-state-and-actions/#toc_computed-values
let
You can define variables straight in the template with let
{{#let (if this.textToUse "Text 1" "Text 2") as |theText|}}
{{#if this.isClickable}}
<button {{on "click" this.onRepostsTotalClickAction}} >
<span>
{{theText}}
<span>
<img src=someIcon />
</button>
{{else}}
<div>
<span>
{{theText}}
<span>
<img src=someIcon />
</div>
{{/if}}
{{/let}}
Docs: https://api.emberjs.com/ember/4.4/classes/Ember.Templates.helpers/methods/let?anchor=let
You could make another component, that would be:
ember g component the-text -gc
<span>
{{#if this.useText1}}
Text 1
{{else}}
Text 2
{{/if}
<span>
and then back your component with the button, you'd have:
{{#if this.isClickable}}
<button {{on "click" this.onRepostsTotalClickAction}} >
<TheText />
<img src=someIcon />
</button>
{{else}}
<div>
<TheText />
<img src=someIcon />
</div>
{{/if}}
element
helper:This is a polyfill: https://github.com/tildeio/ember-element-helper
{{#let (element (if this.isClickable
"button"
"div"
)) as |Tag|}}
<Tag {{if this.isClickable
(modifier "on" "click" this.onClick)
}}
>
<span>
{{#if this.useText1}}
Text 1
{{else}}
Text 2
{{/if}
<span>
<img src=someIcon />
</Tag>
{{/let}}
I think this requires at least [email protected] to get the modifier
helper
Upvotes: 2