3

Super, super new to Ember, so apologies if this is straight forward. I want to know the best way to dynamically change properties in a CSS class rendered within a component.

I made a component, like so:

//route_template.hbs
{{map-view point=model}}

And I pass through point, which has two coordinate properties: model.xCoordinate, and model.yCoordinate.

Here's my component template. You can see I am currently using this hacky inline styling to style the point location on the page:

//component_template.hbs
{{#each point as |mapPoint|}}
   <i class="point-icon" style={{html-safe (concat 'left:' mapPoint.xCoordinate 'px; top:' mapPoint.yCoordinate 'px;')}}></i>
{{/each}}

I know: gross. Is there a better way to do this? Should I make a handlebars helper? An action? If someone could just point me in the general direction, I can take it from there. Thanks so much!

2 Answers 2

2

have a look at my answer here.

probably ember-css-properties is what you're looking for. Another option is a helper or a computed property.

A helper could offer this API:

<i class="point-icon" style={{build-css
  left=(concat mapPoint.xCoordinate 'px')
  top=(concat mapPoint.yCoordinate 'px')
}}></i>

or even assume px by default:

<i class="point-icon" style={{build-css
  left=concat mapPoint.xCoordinate
  top=concat mapPoint.yCoordinate
}}></i>

if you want to use a computed property you would do this in your template:

<i class="point-icon" style={{myComputedStyle}}></i>

and this in your style

myComputedStyle: computed('mapPoint.{xCoordinate,yCoordinate}', {
  get() {
    return htmlSafe(`
      left: ${xCoordinate}px;
      top: ${yCoordinate}px;
    `);
  }
}),

be careful: with all of theese (except ember-css-properties) you need to understand the implications:

If the user can manipulate mapPoint.xCoordinate or mapPoint.yCoordinate to an unexpected value you may open a security hole!

Sign up to request clarification or add additional context in comments.

Comments

-1

You don't need to use the concat helper in <> type elements. You can do this instead

<i class="point-icon" style="left: {{mapPoint.xCoordinate}}px; top: {{mapPoint.yCoordinate}}px;"></i>

For {{}} blocks though you'll need to use concat

{{my-component style=(concat 'left: ' mapPoint.xCoordinate 'px; top: ' mapPoint.yCoordinate 'px;')}}

Also, if I'm correct, you only need to do html safe if you have markups in your string.

See https://guides.emberjs.com/v3.1.0/templates/writing-helpers/#toc_escaping-html-content

3 Comments

I think the value must be properly escaped otherwise you will get a deprecation warning.
I tried it in Ember Twiddle. Didn't get any warnings.
Interesting.. I could've sworn that html-safe is only needed when you have markup in your strings. In his case it was just numbers. Do you have in docs on when to use html-safe? I mean you pretty much have to do html safe everywhere if you're concatinating strings for html attributes if we follow the rule that "it's not just for markups". e.g. <div class="my-class {{foobar}}"></div> will the class need to be html-safe too?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.