first stab at deep two-way binding

pull/31/head
Rich-Harris 8 years ago
parent fa60968ae1
commit 263a08f155

@ -235,17 +235,29 @@ export default function generate ( parsed, template ) {
}
else if ( attribute.type === 'Binding' ) {
if ( attribute.value in current.contexts ) {
throw new Error( `Can only bind top-level properties` );
}
const parts = attribute.value.split( '.' );
const contextual = parts[0] in current.contexts;
const handler = current.counter( `${name}ChangeHandler` );
let setter;
if ( contextual ) {
allUsedContexts.add( parts[0] );
setter = deindent`
var context = this.__context.${parts[0]};
context.${parts.slice( 1 ).join( '.' )} = this.value;
component.set({ ${current.contextChain[0]}: component.get( '${current.contextChain[0]}' ) });
`;
} else {
setter = `component.set({ ${attribute.value}: ${name}.value });`;
}
initStatements.push( deindent`
var ${name}_updating = false;
function ${handler} () {
${name}_updating = true;
component.set({ ${attribute.value}: ${name}.value });
${setter}
${name}_updating = false;
}
@ -253,7 +265,7 @@ export default function generate ( parsed, template ) {
` );
updateStatements.push( deindent`
if ( !${name}_updating ) ${name}.value = root.${attribute.value};
if ( !${name}_updating ) ${name}.value = ${contextual ? attribute.value : `root.${attribute.value}`}
` );
teardownStatements.push( deindent`

@ -49,7 +49,7 @@ export function readBindingDirective ( parser, start, name ) {
null
);
const value = parser.read( /[a-zA-Z_$][a-zA-Z0-9_$]*/ ); // TODO keypaths? /([a-zA-Z_$][a-zA-Z0-9_$]*)(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*/
const value = parser.read( /([a-zA-Z_$][a-zA-Z0-9_$]*)(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*/ );
if ( !value ) parser.error( `Expected valid property name` );
if ( quoteMark ) {

@ -0,0 +1,31 @@
import * as assert from 'assert';
export default {
data: {
items: [
{ description: 'one' },
{ description: 'two' },
{ description: 'three' }
]
},
html: `<div><input><p>one</p></div><div><input><p>two</p></div><div><input><p>three</p></div><!--#each items-->`,
test ( component, target, window ) {
const inputs = [ ...target.querySelectorAll( 'input' ) ];
assert.equal( inputs[0].value, 'one' );
const event = new window.Event( 'input' );
inputs[1].value = 'four';
inputs[1].dispatchEvent( event );
assert.equal( target.innerHTML, `<div><input><p>one</p></div><div><input><p>four</p></div><div><input><p>three</p></div><!--#each items-->` );
const items = component.get( 'items' );
items[2].description = 'five';
component.set({ items });
assert.equal( inputs[2].value, 'five' );
assert.equal( target.innerHTML, `<div><input><p>one</p></div><div><input><p>four</p></div><div><input><p>five</p></div><!--#each items-->` );
}
};

@ -0,0 +1,3 @@
{{#each items as item}}
<div><input bind:value='item.description'><p>{{item.description}}</p></div>
{{/each}}
Loading…
Cancel
Save