blob: 785d8c0e3b159e08b1e002e079e29bea647a534e [file] [log] [blame]
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of mdv;
/** Extensions to [Element]s that behave as templates. */
class _TemplateExtension extends _ElementExtension {
var _model;
BindingDelegate _bindingDelegate;
_TemplateIterator _templateIterator;
bool _scheduled = false;
_TemplateExtension(Element node) : super(node);
Element get node => super.node;
NodeBinding createBinding(String name, model, String path) {
switch (name) {
case 'bind':
case 'repeat':
case 'if':
if (_templateIterator == null) {
_templateIterator = new _TemplateIterator(node);
}
// TODO(jmesserly): why do we do this here and nowhere else?
if (path == null) path = '';
return new _TemplateBinding(node, name, model, path);
default:
return super.createBinding(name, model, path);
}
}
/**
* Creates an instance of the template.
*/
DocumentFragment createInstance(model, BindingDelegate delegate) {
var template = node.ref;
if (template == null) template = node;
var instance = _createDeepCloneAndDecorateTemplates(
template.ref.content, delegate);
if (_instanceCreated != null) {
for (var callback in _instanceCreated) callback(instance);
}
_addBindings(instance, model, delegate);
_addTemplateInstanceRecord(instance, model);
return instance;
}
/**
* The data model which is inherited through the tree.
*/
get model => _model;
void set model(value) {
_model = value;
_ensureSetModelScheduled();
}
/**
* The binding delegate which is inherited through the tree. It can be used
* to configure custom syntax for `{{bindings}}` inside this template.
*/
BindingDelegate get bindingDelegate => _bindingDelegate;
void set bindingDelegate(BindingDelegate value) {
_bindingDelegate = value;
_ensureSetModelScheduled();
}
_ensureSetModelScheduled() {
if (_scheduled) return;
_scheduled = true;
runAsync(_setModel);
}
void _setModel() {
_scheduled = false;
_addBindings(node, _model, _bindingDelegate);
}
}
class _TemplateBinding extends NodeBinding {
// TODO(jmesserly): MDV uses TemplateIterator as the node, see:
// https://github.com/Polymer/mdv/issues/127
_TemplateBinding(node, name, model, path)
: super(node, name, model, path) {
_mdv(node)._templateIterator.inputs.bind(property, model, path);
}
// These are no-ops because we don't use the underlying PathObserver.
void _observePath() {}
void boundValueChanged(newValue) {}
void close() {
if (closed) return;
var templateIterator = _mdv(node)._templateIterator;
if (templateIterator != null) templateIterator.inputs.unbind(property);
super.close();
}
}