fix binding group with if block

pull/8373/head
tanhauhau 4 years ago
parent 5c14bc5f01
commit 3cba111254

@ -505,7 +505,7 @@ export default class Block {
render_binding_groups() { render_binding_groups() {
for (const binding_group of this.binding_groups) { for (const binding_group of this.binding_groups) {
binding_group.render(); binding_group.render(this);
} }
} }
} }

@ -27,8 +27,8 @@ export interface BindingGroup {
contexts: string[]; contexts: string[];
list_dependencies: Set<string>; list_dependencies: Set<string>;
keypath: string; keypath: string;
elements: Identifier[]; add_element: (block: Block, element: Identifier) => void;
render: () => void; render: (block: Block) => void;
} }
export default class Renderer { export default class Renderer {

@ -153,7 +153,7 @@ export default class BindingWrapper {
case 'group': case 'group':
{ {
block.renderer.add_to_context('$$binding_groups'); block.renderer.add_to_context('$$binding_groups');
this.binding_group.elements.push(this.parent.var); this.binding_group.add_element(block, this.parent.var);
if ((this.parent as ElementWrapper).has_dynamic_value) { if ((this.parent as ElementWrapper).has_dynamic_value) {
update_or_condition = (this.parent as ElementWrapper).dynamic_value_condition; update_or_condition = (this.parent as ElementWrapper).dynamic_value_condition;
@ -321,7 +321,10 @@ function get_binding_group(renderer: Renderer, binding: BindingWrapper, block: B
parent = parent.parent; parent = parent.parent;
} }
const elements = []; // when using bind:group with logic blocks, the <input> with bind:group
// maybe scatter across different blocks
// will need to keep track all the <input> elements that has the same bind:group within the same block
const elements = new Map<Block, any>();
contexts.forEach(context => { contexts.forEach(context => {
renderer.add_to_context(context, true); renderer.add_to_context(context, true);
@ -341,8 +344,13 @@ function get_binding_group(renderer: Renderer, binding: BindingWrapper, block: B
contexts, contexts,
list_dependencies, list_dependencies,
keypath, keypath,
elements, add_element(block, element) {
render() { if (!elements.has(block)) {
elements.set(block, []);
}
elements.get(block).push(element);
},
render(block) {
const local_name = block.get_unique_name('binding_group'); const local_name = block.get_unique_name('binding_group');
const binding_group = block.renderer.reference('$$binding_groups'); const binding_group = block.renderer.reference('$$binding_groups');
block.add_variable(local_name); block.add_variable(local_name);
@ -360,7 +368,7 @@ function get_binding_group(renderer: Renderer, binding: BindingWrapper, block: B
); );
} }
block.chunks.hydrate.push( block.chunks.hydrate.push(
b`${local_name}.p(${elements})` b`${local_name}.p(${elements.get(block)})`
); );
block.chunks.destroy.push( block.chunks.destroy.push(
b`${local_name}.r()` b`${local_name}.r()`

@ -359,7 +359,7 @@ export function get_binding_group_value(group, __value, checked) {
return Array.from(value); return Array.from(value);
} }
export function init_binding_group(group) { export function init_binding_group(group: HTMLInputElement[]) {
let _inputs: HTMLInputElement[]; let _inputs: HTMLInputElement[];
return { return {
/* push */ p(...inputs: HTMLInputElement[]) { /* push */ p(...inputs: HTMLInputElement[]) {

@ -0,0 +1,39 @@
export default {
async test({ assert, target, component, window }) {
const button = target.querySelector('button');
const clickEvent = new window.Event('click');
const changeEvent = new window.Event('change');
const [input1, input2] = target.querySelectorAll('input[type="checkbox"]');
function validate_inputs(v1, v2) {
assert.equal(input1.checked, v1);
assert.equal(input2.checked, v2);
}
assert.deepEqual(component.test, []);
validate_inputs(false, false);
component.test = ['a', 'b'];
validate_inputs(true, true);
input1.checked = false;
await input1.dispatchEvent(changeEvent);
assert.deepEqual(component.test, ['b']);
input2.checked = false;
await input2.dispatchEvent(changeEvent);
assert.deepEqual(component.test, []);
input1.checked = true;
input2.checked = true;
await input1.dispatchEvent(changeEvent);
await input2.dispatchEvent(changeEvent);
assert.deepEqual(component.test, ['b', 'a']);
await button.dispatchEvent(clickEvent);
input1.checked = false;
await input1.dispatchEvent(changeEvent);
assert.deepEqual(component.test, []);
}
};

@ -0,0 +1,14 @@
<script>
export let test = [];
let hidden = false
</script>
<button on:click={() => hidden = !hidden}>
{hidden ? "show" : "hide"} b
</button>
<label>a <input type="checkbox" bind:group={test} value="a" /></label>
{#if !hidden}
<label>b <input type="checkbox" bind:group={test} value="b" /></label>
{/if}
<label>c <input value="just here, so b is not the last input" /></label>

@ -0,0 +1,33 @@
export default {
async test({ assert, target, component, window }) {
const button = target.querySelector('button');
const clickEvent = new window.Event('click');
const changeEvent = new window.Event('change');
const [input1, input2] = target.querySelectorAll('input[type="radio"]');
function validate_inputs(v1, v2) {
assert.equal(input1.checked, v1);
assert.equal(input2.checked, v2);
}
component.test = 'a';
validate_inputs(true, false);
component.test = 'b';
validate_inputs(false, true);
input1.checked = true;
await input1.dispatchEvent(changeEvent);
assert.deepEqual(component.test, 'a');
input2.checked = true;
await input2.dispatchEvent(changeEvent);
assert.deepEqual(component.test, 'b');
await button.dispatchEvent(clickEvent);
input1.checked = true;
await input1.dispatchEvent(changeEvent);
assert.deepEqual(component.test, 'a');
}
};

@ -0,0 +1,14 @@
<script>
export let test;
let hidden = false
</script>
<button on:click={() => hidden = !hidden}>
{hidden ? "show" : "hide"} b
</button>
<label>a <input type="radio" bind:group={test} value="a" /></label>
{#if !hidden}
<label>b <input type="radio" bind:group={test} value="b" /></label>
{/if}
<label>c <input value="just here, so b is not the last input" /></label>
Loading…
Cancel
Save