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

[v2] Fix issue where class directives wouldn't work with spread props and class prop #3236

Closed
wants to merge 4 commits into from

Conversation

umanghome
Copy link
Contributor

@umanghome umanghome commented Jul 13, 2019

Currently, if there is any spread prop along with a dynamic class prop on the element, the class: directives stop working once the value of the variable that class was dependent on changes. This is because it sets the class prop of the DOM element directly, removed the class attached by the class: directive. And since the variable affecting the directive hasn't changed, a class for it is not applied again.

This should not happen, and class: directive should work just fine with spread props.

I have added tests in this PR as well, which were failing with v2.16.1, but are fixed with the succeeding commits.

Can't save a v2 REPL anymore, so adding an example in the PR description itself.

WithoutSpread.svelte

<div
  class={allClasses}
  class:reverse
>
  <slot></slot>
</div>

<script>
  export default {
    data: () => ({
      classes: [],
      reverse: false,
    }),

    computed: {
      allClasses: ({ classes }) => {
        const defaultClasses = ['without-spread'];

        return defaultClasses.concat(classes).join(' ');
      }
    }
  }
</script>

withSpread.svelte

<div
  class={allClasses}
  class:reverse
  {...attributes}
>
  <slot></slot>
</div>

<script>
  export default {
    data: () => ({
      classes: [],
      reverse: false,
    }),

    computed: {
      allClasses: ({ classes }) => {
        const defaultClasses = ['with-spread'];

        return defaultClasses.concat(classes).join(' ');
      }
    }
  }
</script>

App.svelte

<div>
	<input type="checkbox" id="round" bind:checked="round" />
	<label for="round">Round</label>
</div>

<WithoutSpread
	{classes}
	{reverse}
>
	Without Spread
</WithoutSpread>

<WithSpread
	{reverse}
	{classes}
	attributes={{
		'aria-label': 'With Spread'
	}}
>
	With Spread
</WithSpread>

<script>

export default {
	components: {
		WithoutSpread: './WithoutSpread.svelte',
		WithSpread: './WithSpread.svelte',
	},

	data: () => ({
		reverse: true,
	}),

	computed: {
		classes: ({ round }) => {
			const allClasses = [];

			if (round) {
				allClasses.push('round');
			}

			return allClasses;
		}
	},
}

</script>

<style>
	label, input {
		display: inline-block;
		vertical-align: top;
	}
</style>

The generated update functions, with version 2.16.1:

WithoutSpread.svelte

p: function update(changed, ctx) {
	if (changed.allClasses) {
		div.className = ctx.allClasses;
	}

	if ((changed.allClasses || changed.reverse)) {
		toggleClass(div, "reverse", ctx.reverse);
	}
}

WithSpread.svelte

p: function update(changed, ctx) {
	setAttributes(div, getSpreadUpdate(div_levels, [
		(changed.allClasses) && { class: ctx.allClasses },
		(changed.attributes) && ctx.attributes
	]));

	if (changed.reverse) {
		toggleClass(div, "reverse", ctx.reverse);
	}
}

The generated update functions, with changes in this PR:

WithoutSpread.svelte

p: function update(changed, ctx) {
	if (changed.allClasses) {
		div.className = ctx.allClasses;
	}

	if ((changed.allClasses || changed.reverse)) {
		toggleClass(div, "reverse", ctx.reverse);
	}
}

WithSpread.svelte

p: function update(changed, ctx) {
	setAttributes(div, getSpreadUpdate(div_levels, [
		(changed.allClasses) && { class: ctx.allClasses },
		(changed.attributes) && ctx.attributes
	]));

	if ((changed.allClasses || changed.reverse)) {
		toggleClass(div, "reverse", ctx.reverse);
	}
}

@umanghome
Copy link
Contributor Author

This issue might fix #2707, but only for v2 and not for v3. Once this PR gets merged and the v2 bug is fixed, someone can pick up similar changes for v3.

@umanghome umanghome force-pushed the v2-class-deps-fix branch from 896b921 to 7fae587 Compare July 13, 2019 11:28
@umanghome umanghome changed the title [v2] Fix issue where class directives wouldn't work with spread attributes and class attribute [v2] Fix issue where class directives wouldn't work with spread props and class prop Jul 14, 2019
@Conduitry
Copy link
Member

At this point, I don't think we're really in a position to start porting specific fixes back to v2. #2707 was but one of a host of buggy edge cases around attribute spreads that were probably all present in v2 as well. If someone wants to maintain an unofficial 'v2 with backports' fork, they are of course free to do so.

@Conduitry Conduitry closed this Apr 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants