Issue #3541Opened June 15, 2021by deiga0 reactions

[QUESTION] What is the idiomatic way to append and remove classes from components?

Question

Hey there 👋 Love the editor!

We're using traits to modify what classes a component has, but that feels a bit hacky as you have to redeclare ALL classnames for each trait selection

Here a simple example:

{
    type: 'select',
    label: 'Accent',
    name: 'class',
    options: [
        {value: 'button button-primary-green button-small', name: 'Primary green small'},
        {value: 'button button-secondary-green button-small', name: 'Secondary green small'},
        {value: 'button button-tertiary-green button-small', name: 'Tertiary green small'},
        {value: 'button', name: '---'},
        {value: 'button button-primary-green button-medium', name: 'Primary green medium'},
        {value: 'button button-secondary-green button-medium', name: 'Secondary green medium'},
        {value: 'button button-tertiary-green button-medium', name: 'Tertiary green medium'},
    ]
}

Each trait option has to have all the classes defined, because otherwise it will remove any existing classes. This feels like the wrong way to do this, but we haven't been able to figure out any other in-built way to modify classes of a component.

What would be the correct way to do this?

Answers (2)

krishnaeverestengineering• June 19, 20210 reactions

@deiga we are doing something like this.

{
      defaults: ->
        {
          name: type
          type: type
          tagName: 'div'
          socialElement: 'web'
          icons: {
            twitter: 'fa-twitter-square'
            linkedin: 'fa-linkedin-square'
            web: 'fa-globe'
          }
          components: {
            type: 'link'
            toolbar: []
          }
          attributes: {
            'class': "social_element fa fa-twitter-square"
          }
          traits: [
            {
              type: 'select'
              label: 'Icon'
              name: 'socialElement'
              changeProp: 1
              options: []
            }, {
              name: 'href'
              changeProp: 1
            }
          ]
        }

      init: ->
        this.listenTo(this, 'change:href', @onSocialUrlChange.bind(this))
        this.listenTo(this, 'change:socialElement', @onSocialIconChange.bind(this))

        @initSettings()
        @updateTraitValues()

      updateTraitValues: ->
        @_initSocialIcon()

      _initSocialIcon: ->
        icons = @attributes.icons
        classes = @getClasses()
        icon = ''
        for cls in classes
          icon = Object.keys(icons).find((key) -> icons[key] == cls)
          break if icon

        this.set('socialElement', icon || 'twitter')

      initSettings: ->
        icons = @attributes.icons
        @updateTrait('socialElement', {
          options: [
            { id: 'twitter', name: 'Twitter', value: 'twitter' },
            { id: 'linkedin', name: 'Linkedin', value: 'linkedin'},
            { id: 'web', name: 'Web', value: 'web' }
          ]
        })

      onSocialIconChange: (model, value) ->
        newClassSet = ['social_element', 'fa']
        model.setClass(newClassSet.concat(@attributes.icons[value]))
    }
artf• June 24, 20210 reactions

I'd attach the trait to some component property instead of the class attribute, and based on the value I'd use properly removeClass and addClass

Related Questions and Answers

Continue research with similar issue discussions.

Paid Plugins That Match This Issue

Curated by issue keywords and label relevance to help you ship faster.

View all plugins

Loading paid plugin recommendations...

Browse Plugin Categories

Jump directly to plugin category pages on the marketplace.