[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)
@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]))
}
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.
Issue #2193
[QUESTION] Reset trait on edit the content of a custom component
Hi, I have a custom component which content can be changed by switching trait select options, but also can be edited similar to the text co...
Issue #2404
Question: how to observe children changes in component
Is there an easy way to subscribe/listen to changes in the components/children of my custom component type? Perhaps an event I can subscrib...
Issue #3237
Add Trait For wrapper
Hi @artf I've added trait for wrapper this way. How can I perform the init function for the same Here is the code @artf Could you please he...
Issue #2456
[QUESTION] (Possibly a bug) How to apply traits to components used for GrapesJs initialization
I am using This works but only for blocks which are added/drag-dropped to the editor manually after it is initialized. If we supply compone...
Paid Plugins That Match This Issue
Curated by issue keywords and label relevance to help you ship faster.
Loading paid plugin recommendations...
Browse Plugin Categories
Jump directly to plugin category pages on the marketplace.