9

For example: Ember components allow you to add a classNames array and those classes will be added to the main div of the component. say we have this component called new-div

export default Ember.Component.extend({
    classNames: ['container']
});

then if you inspect this component when rendered you will see:

<div id="ember595" class="ember-view container">
...
<div>

this is fine but my issue is what if i want to use this component as a fluid container sometimes and sometimes I might want to make it a jumbotron etc.

Is there a way to do this in the html and have the component.js apply it correctly?

{{new-div extra-classes='class1,class2'}}

then in the component.js:

export default Ember.Component.extend({
    classNames: [this.get('class-names')]
});
Soviut
  • 88,194
  • 49
  • 192
  • 260
pfg
  • 213
  • 2
  • 7

5 Answers5

14

The @dmk'solution is the cleanest one, but if your scenario it is not working you can use classNameBindings:

export default Ember.Component.extend({
  classNameBindings: ['getClassNames'],
  getClassNames: Ember.computed('extra-classes', function(){
    return this.get('extra-classes').replace(',', ' ');
  })
})
Community
  • 1
  • 1
fguillen
  • 36,125
  • 23
  • 149
  • 210
  • This one is great when you want the component to control its own class names. – Skitterm Nov 08 '17 at 00:52
  • this could just be `classNameBindings: ['myClassNames'],` where `myClassNames` is an attribute declared on the template. no computed property necessary (of course in your example it is because OP has a comma-delimited list). – Jason Nov 28 '17 at 21:46
13

You can add class names simply by specifying them inside the class attribute on your component:

{{new-div class="class1 class2"}}
dimusic
  • 4,123
  • 2
  • 28
  • 31
  • isn't the attribute `classNames` or was this changed recently? – akst Jan 28 '16 at 06:29
  • 1
    @ABot I think `class` works since they moved to htmlbars and it's a better option, but `classNames` still works too. – dimusic Jan 28 '16 at 08:39
1

If you're not adding too many classes, it's easy enough with class name bindings:

export default Ember.Component.extend({
  classNameBindings: [
    'foo:bar',
    'foo:baz',
  ],
});

And set the value of foo:

{{new-div foo=true}}

This will toggle on all the above class names.

See: https://api.emberjs.com/ember/release/classes/Component/properties/classNameBindings?anchor=classNameBindings

Of course, you could get tricky with computed properties and mapping an array. Also: I like to avoid assigning dynamic class names to components explicitly. Things become messy rather quickly.

Rimian
  • 36,864
  • 16
  • 117
  • 117
0

Just as an alternative one could use something like this

export default Ember.Component.extend({
attributeBindings:  ['style'],

    style: function(){
        return new Ember.Handlebars.SafeString('class="foo bar"');
    }.property(),
});

// NOT sure on this one untested
export default Ember.Component.extend({
attributeBindings:  ['classNames'],

    classNames: function(){
        return 'foo bar';
    }.property(),
});
0

If someone is using ember-component-css, you may want to try out the join-classes or the local-class attribute helper.

{{join-classes styles.myclass1 attributeValue}}

attributeValue can be a value from the component's controller (I mean component.js), or an item inside an each block.

If styles.myclass1 = .class1, and attributeValue = .dummy, then the selectors would be available as .class1.dummy in the styles.css.

local-class={{(concat "myclass-" myvalue)}}

If myvalue = 'part', then with this, the generated classname would include tree-to-component_myclass-part__sdfje2jbr2 (last part is generated id), and would be accessible in the stylesheet as .myclass-part.

Jayant Bhawal
  • 2,044
  • 2
  • 31
  • 32