Grapesjs: Changing CSS properties on a component with an existing class modifies that class instead of adding a new one

Created on 10 Oct 2017  路  13Comments  路  Source: artf/grapesjs

You can see this in action on the demo (http://grapesjs.com/demo.html). Select one of the nav items ('Web' for example) - note that it has an existing class of menu-item. If you now change some of the properties, such as text alignment, it applies those changes to the menu-item class, which affects the other instances ('Template', 'Builder').

Is it possible to force GrapesJS to apply a new 'unique' class and apply the changes there - similar to how it works if you make changes to a component with no existing classes (c1234 for example)?

Ultimately I want any Style changes to only apply to the selected item - never to other instances of the same type.

Thanks

Most helpful comment

I was thinking that the behaviour could be something like this:

Default (current setup):

  • If element has no classes, create unique class based on cid and apply styles
  • If element has classes, apply styles to the union of those classes (or whatever classes are selected in the UI)

Toggled behaviour

  • Test if element has an existing class based on the cid, if one does not exist, create one
  • Always apply custom styles to the cid class only

All 13 comments

I'd say you have 2 options:

  1. Just deselect the class, in this case, the style manager scope will change to the component and not the rule
  2. Add a new class to the component, instead of .menu-item rule you will get .menu-item.your-new-class

I would probably prefer some kind of config setting I could toggle off to change the behaviour, but I've managed to find a workaround. In my case all the content comes from our own system (no worry about external content etc), so I found all the instances where this was a problem and converted them into mini components - I then automatically add a unique class when the component is created.

I think that this would be nice to have as a config setting though, regardless. In our use case (and many others, I'm sure), the end users are unlikely to be HTML savvy and so having them deal with classes and selectors and the like is going to be confusing. We've actually hidden the css class selector panel from view, hence why I was looking for an automated solution.

Exactly, how would you expect this config setting to work? I mean, just ignore classes in Style Manager and apply always the style on the component?

I was thinking that the behaviour could be something like this:

Default (current setup):

  • If element has no classes, create unique class based on cid and apply styles
  • If element has classes, apply styles to the union of those classes (or whatever classes are selected in the UI)

Toggled behaviour

  • Test if element has an existing class based on the cid, if one does not exist, create one
  • Always apply custom styles to the cid class only

thanks @thecodefish I'll try to figure out the best way to do so

Hi @thecodefish what do you think about this approach?
https://codepen.io/artf/pen/jaaKvq

You will see there how to make selectors private (not stylable by the user) and the usage of the new avoidInlineStyle option which allows you to style components (not class selectors) without losing the responsivity and the use of states (eg. :hover)

@artf I just started to use your IDE today. Thanks for making impossible possible.

I have the same concern that @thecodefish has and here is my suggestion.
Give a simple dropdown with 2 fixed options as,
Applies To : "Selected Item", "Selected Type"

By default (when select a component) it is set to "Selected Item". And when the component is initialized, create a random class and link it to "Selected Item" option and the common class is linked to "Selected Type".

Ex: menu-item

When "Selected Item" option is selected
.menu-item -> unchecked
.random -> checked
image

When "Selected Type" option is selected
.menu-item -> checked
(no other classes other than user defined)
image

User should not be able to check/uncheck factory made classes of "Applies To" options, but user should be able to add user's own classes by adding new classes as now.
By this way, "Applies To" defines a factory setting.

  • It is better if we can add following marked area into a according or some sort of a collapsible area which is collapsed by default.
    image
    With this nobody wants to hide it manually as @thecodefish did, but feature stays and however users can add their own styles if they want with user defined classes. And users can check/uncheck those classes which they have added.

I see one major concern which is now you have to have class config states for both the options "Selected Type" and "Selected Item" and that could effect to the whole IDE/system :(

This could be a very user friendly change if you can make it work.
I was going to change it as I described, but since you are already up to it I though to wait for you answer.
If it is not possible I will make the change an send you a pull request, but I'm not a frontend guy so code could be so ugly and hacky and will take some time and I'm going to hide the complete custom class selection area and so the concern I was thinking and mentioned above will go away - easy for me.

Thanks again!

Hey @sura2k I think what you've described is basically the concept I've done here
https://codepen.io/artf/pen/jaaKvq
By default, all "factory classes" are not visible so when you select the component "Selected Item" is what you get. In the demo, with the last line, I've basically disabled the possibility to add new classes but if you remove it the user is able to create its own classes.
By the way, I think your implementation could be made with a plugin (by making use of Selectors and CssComposer) so no need to have it inside the core

Wow..nothing me to worry. It seems avoidInlineStylecovers all the logic I need except the UI part.
@artf Is there a way to override/modify views using a plugin? (I ended up modifying ClassTagsView of core, couldn't find a way to plug a template)

@sura2k unfortunately not everything is overridable (yet)

@artf I think your approach could work quite well (at least for my use case, where I've hidden the selector UI through CSS).

One thing I noticed with my current workaround - is the cid property persisted? I noticed some behaviour whereby if I manually created a class .c232 (for example), after saving/reloading the component list, I would end up with new cids and therefore .c232 .c137 (or the like). I worked around this as well but is this normal behaviour? Would we get the same issues with your update?

not sure but I think this some related to forceClass option (which is true by default)
https://github.com/artf/grapesjs/blob/dev/src/dom_components/model/Components.js#L77
try to disable it

Hi artf, I have a dilemma where I want the user to be able to view, add or remove the current classes on the element (since they will be bootstrap) but when they edit the styles I want them to only target the component not the classes. The solution presented above where the selectors are made private doesn't allow the user to view which classes are applied, I have been unable to figure out how to achieve this with the tools given. Is there any way I can achieve this?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alibouaziz picture alibouaziz  路  3Comments

andre2 picture andre2  路  3Comments

kickbk picture kickbk  路  3Comments

YashPrince picture YashPrince  路  3Comments

ionic666 picture ionic666  路  3Comments