Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1990 remove css class on observable change #2327

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

setagana
Copy link

@setagana setagana commented Dec 6, 2017

This pull request is meant to address Issue 1990.

New functionality for the CSS binding

With this pull request, the CSS binding will accept an array of strings which forms the definitive list of classes for the bound element. Below is my reasoning for this additional behaviour which can (in time) I believe replace the current use of class objects.

This functionality has been added to existing functionality for the sake of backwards compatibility.

Motivations

The CSS binding is inconsistent with other data bindings in the framework.

In its current form, I believe the CSS binding to be the only binding that requires both knowledge of the existing state and the necessary delta in order to reach a desired state. If you start with an element like:

<div data-bind="css: { myFirstClass: true, mySecondClass: true }"></div>

which generates

<div class="myFirstClass mySecondClass"></div>

and you desire to achieve the state:

<div class="myFirstClass myThirdClass"></div>

you are required to emit a change which contains the full delta from initial state to desired state:

<div data-bind="css: { myFirstClass: true, mySecondClass: false, myThirdClass: true }"></div>

Compare this to the text data binding where it is sufficient to emit only the desired state in order to make a change:

<p data-bind="text: 'This text will overwrite anything which was previously bound'"></p>

Presumably this is because the CSS binding was written to work in tandem with directly applied classes like so:

<div class="directly-applied-class" data-bind="css: { binding-applied-class: true }"></div>

However this is itself an inconsistency with other bindings, where directly applied content is overwritten by the data-binding:

<p data-bind="text: 'Text which will be shown'">Text which will be overwritten</p>

With the existing CSS binding functionality, if you do not emit a change for the delta to the desired state, the binding will only ever add classes without removing them. You can compare the behaviours with this pen based on existing functionality and this pen based on the change in this PR.

Knockout observableArrays are easier to manipulate than objects

Using arrays as the input for the CSS binding allows users to leverage the many helpers for array manipulation contained in knockout. For more on this, please refer to the documentation for working with knockout arrays.

Having the bound array be the definitive list of classes makes working with dynamic classes trivial

As raised in issue 1990 and evident from the discussion of pull 1710, working with dynamic classes in the current version of knockout isn't self explanatory. By making the CSS data-binding definitive for the list of classes on an element (as the text binding is for its contents) it becomes trivial to work with static and dynamic classes as shown by this pen using the changes proposed in this PR.

@mbest
Copy link
Member

mbest commented Dec 6, 2017

Related: #930

@mbest
Copy link
Member

mbest commented Sep 30, 2019

You can already use the class binding with string value to achieve this functionality (minus removing fixed classes). If it's important to support arrays in addition to strings, that should be added to the class binding.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants