Skip to content

Commit

Permalink
add support for absolute root ref as ~~/ and support for using root r…
Browse files Browse the repository at this point in the history
…efs (~/, ~~/) with plain API methods

fixes #1958, fixes #2432
  • Loading branch information
evs-chris committed Nov 6, 2016
1 parent 4ae7cda commit cf45190
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/Ractive/construct.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ function initialiseProperties ( ractive ) {
ractive._children.byName = {};
ractive.children = ractive._children;

if(!ractive.component){
if ( !ractive.component ) {
ractive.root = ractive;
ractive.parent = ractive.container = null; // TODO container still applicable?
}
Expand Down
6 changes: 6 additions & 0 deletions src/model/RootModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ export default class RootModel extends Model {

key = unescapeKey( key );
if ( key === '@this' || key === '@global' || key === '@shared' ) return true;
if ( ~key.indexOf( '~/' ) || ~key.indexOf( '~~/' ) ) return true;
if ( hasProp.call( value, key ) ) return true;

// mappings/links and computations
Expand All @@ -137,6 +138,11 @@ export default class RootModel extends Model {
return;
}

if ( key[0] === '~' ) {
if ( key[1] === '~' ) return this.ractive.root.viewmodel.joinKey( key.slice( 3 ) );
key = key.slice( 2 );
}

return this.computations.hasOwnProperty( key ) ? this.computations[ key ] :
super.joinKey( key, opts );
}
Expand Down
2 changes: 1 addition & 1 deletion src/parse/converters/expressions/primary/readReference.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const globals = /^(?:Array|console|Date|RegExp|decodeURIComponent|decodeURI|enco
// keywords are not valid references, with the exception of `this`
const keywords = /^(?:break|case|catch|continue|debugger|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|throw|try|typeof|var|void|while|with)$/;

const prefixPattern = /^(?:\@\.|\@|~\/|(?:\^\^\/(?:\^\^\/)*(?:\.\.\/)*)|(?:\.\.\/)+|\.\/(?:\.\.\/)*|\.)/;
const prefixPattern = /^(?:\@\.|\@|~\/|~~\/|(?:\^\^\/(?:\^\^\/)*(?:\.\.\/)*)|(?:\.\.\/)+|\.\/(?:\.\.\/)*|\.)/;
const specials = /^(key|index|keypath|rootpath|this|global)/;
const specialCall = /^\s*\(/;

Expand Down
5 changes: 4 additions & 1 deletion src/view/resolvers/resolveReference.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ export default function resolveReference ( fragment, ref ) {
if ( ref === '.' ) return fragment.findContext();

// ancestor references
if ( ref[0] === '~' ) return fragment.ractive.viewmodel.joinAll( splitKeypath( ref.slice( 2 ) ) );
if ( ref[0] === '~' ) {
if ( ref[1] === '~' ) return fragment.ractive.root.viewmodel.joinAll( splitKeypath( ref.slice( 3 ) ) );
return fragment.ractive.viewmodel.joinAll( splitKeypath( ref.slice( 2 ) ) );
}

// scoped references
if ( ref[0] === '.' || ref[0] === '^' ) {
Expand Down
50 changes: 50 additions & 0 deletions test/browser-tests/references.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,4 +249,54 @@ export default function() {

t.htmlEqual( fixture.innerHTML, 'yepyep' );
});

test( 'component tree root data can be accessed with ~~/ (#2432)', t => {
const cmp = Ractive.extend({
template: '{{#with some.path}}{{~/foo}} {{~~/foo}}{{/with}}',
data: {
foo: 'cmp',
some: { path: {} }
}
});
new Ractive({
target: fixture,
template: '{{#with other.path}}<cmp />{{/with}}',
data: {
foo: 'root',
other: { path: {} }
},
components: { cmp }
});

t.htmlEqual( fixture.innerHTML, 'cmp root' );
});

test( 'root model will deal with ~/ and ~~/ references (#2432)', t => {
const cmp = Ractive.extend({
data: { foo: { bar: 'cmp' } }
});
const r = new Ractive({
target: fixture,
data: { foo: { bar: 'root' } },
template: '<cmp />',
components: { cmp }
});

const c = r.findComponent( 'cmp' );

t.equal( c.get( '~/foo.bar' ), 'cmp' );
t.equal( c.get( '~~/foo.bar' ), 'root' );
});

test( `trying to set a relative keypath from instance set warns and doesn't do unexpected things`, t => {
onWarn( w => {
t.ok( /relative keypath.*non-relative.*getNodeInfo.*event object/.test( w ) );
});

const r = new Ractive();

r.set( '.foo.bar', 'nope' );
t.ok( !r.get( 'foo.bar' ) );
t.ok( !( '' in r.get() ) );
});
}

0 comments on commit cf45190

Please sign in to comment.