feat(render): don’t use the reflector for setting properties
BREAKING CHANGES: - host actions don't take an expression as value any more but only a method name, and assumes to get an array via the EventEmitter with the method arguments. - Renderer.setElementProperty does not take `style.`/... prefixes any more. Use the new methods `Renderer.setElementAttribute`, ... instead Part of #2476 Closes #2637
This commit is contained in:
@ -1,7 +1,6 @@
|
||||
library angular.core.facade.dom;
|
||||
|
||||
import 'dart:html';
|
||||
import 'dart:js' show JsObject;
|
||||
import 'dom_adapter.dart' show setRootDomAdapter;
|
||||
import 'generic_browser_adapter.dart' show GenericBrowserDomAdapter;
|
||||
import '../facade/browser.dart';
|
||||
@ -97,9 +96,28 @@ final _keyCodeToKeyMap = const {
|
||||
};
|
||||
|
||||
class BrowserDomAdapter extends GenericBrowserDomAdapter {
|
||||
js.JsFunction _setProperty;
|
||||
js.JsFunction _getProperty;
|
||||
js.JsFunction _hasProperty;
|
||||
BrowserDomAdapter() {
|
||||
_setProperty = js.context.callMethod('eval', ['(function(el, prop, value) { el[prop] = value; })']);
|
||||
_getProperty = js.context.callMethod('eval', ['(function(el, prop) { return el[prop]; })']);
|
||||
_hasProperty = js.context.callMethod('eval', ['(function(el, prop) { return prop in el; })']);
|
||||
}
|
||||
static void makeCurrent() {
|
||||
setRootDomAdapter(new BrowserDomAdapter());
|
||||
}
|
||||
bool hasProperty(Element element, String name) =>
|
||||
_hasProperty.apply([element, name]);
|
||||
|
||||
void setProperty(Element element, String name, Object value) =>
|
||||
_setProperty.apply([element, name, value]);
|
||||
|
||||
getProperty(Element element, String name) =>
|
||||
_getProperty.apply([element, name]);
|
||||
|
||||
invoke(Element element, String methodName, List args) =>
|
||||
this.getProperty(element, methodName).apply(args, thisArg: element);
|
||||
|
||||
// TODO(tbosch): move this into a separate environment class once we have it
|
||||
logError(error) {
|
||||
@ -108,7 +126,7 @@ class BrowserDomAdapter extends GenericBrowserDomAdapter {
|
||||
|
||||
@override
|
||||
Map<String, String> get attrToPropMap => const <String, String>{
|
||||
'innerHtml': 'innerHtml',
|
||||
'innerHtml': 'innerHTML',
|
||||
'readonly': 'readOnly',
|
||||
'tabindex': 'tabIndex',
|
||||
};
|
||||
@ -221,8 +239,6 @@ class BrowserDomAdapter extends GenericBrowserDomAdapter {
|
||||
ShadowRoot getShadowRoot(Element el) => el.shadowRoot;
|
||||
Element getHost(Element el) => (el as ShadowRoot).host;
|
||||
clone(Node node) => node.clone(true);
|
||||
bool hasProperty(Element element, String name) =>
|
||||
new JsObject.fromBrowserObject(element).hasProperty(name);
|
||||
List<Node> getElementsByClassName(Element element, String name) =>
|
||||
element.getElementsByClassName(name);
|
||||
List<Node> getElementsByTagName(Element element, String name) =>
|
||||
|
@ -50,6 +50,12 @@ var _chromeNumKeyPadMap = {
|
||||
|
||||
export class BrowserDomAdapter extends GenericBrowserDomAdapter {
|
||||
static makeCurrent() { setRootDomAdapter(new BrowserDomAdapter()); }
|
||||
hasProperty(element, name: string) { return name in element; }
|
||||
setProperty(el: /*element*/ any, name: string, value: any) { el[name] = value; }
|
||||
getProperty(el: /*element*/ any, name: string): any { return el[name]; }
|
||||
invoke(el: /*element*/ any, methodName: string, args: List<any>): any {
|
||||
el[methodName].apply(el, args);
|
||||
}
|
||||
|
||||
// TODO(tbosch): move this into a separate environment class once we have it
|
||||
logError(error) { window.console.error(error); }
|
||||
@ -152,7 +158,6 @@ export class BrowserDomAdapter extends GenericBrowserDomAdapter {
|
||||
getShadowRoot(el: HTMLElement): DocumentFragment { return (<any>el).shadowRoot; }
|
||||
getHost(el: HTMLElement): HTMLElement { return (<any>el).host; }
|
||||
clone(node: Node) { return node.cloneNode(true); }
|
||||
hasProperty(element, name: string) { return name in element; }
|
||||
getElementsByClassName(element, name: string) { return element.getElementsByClassName(name); }
|
||||
getElementsByTagName(element, name: string) { return element.getElementsByTagName(name); }
|
||||
classList(element): List<any> {
|
||||
|
@ -16,6 +16,11 @@ function _abstract() {
|
||||
* Provides DOM operations in an environment-agnostic way.
|
||||
*/
|
||||
export class DomAdapter {
|
||||
hasProperty(element, name: string): boolean { throw _abstract(); }
|
||||
setProperty(el: /*element*/ any, name: string, value: any) { throw _abstract(); }
|
||||
getProperty(el: /*element*/ any, name: string): any { throw _abstract(); }
|
||||
invoke(el: /*element*/ any, methodName: string, args: List<any>): any { throw _abstract(); }
|
||||
|
||||
logError(error) { throw _abstract(); }
|
||||
|
||||
/**
|
||||
@ -70,7 +75,6 @@ export class DomAdapter {
|
||||
getHost(el): any { throw _abstract(); }
|
||||
getDistributedNodes(el): List<any> { throw _abstract(); }
|
||||
clone(node): any { throw _abstract(); }
|
||||
hasProperty(element, name: string): boolean { throw _abstract(); }
|
||||
getElementsByClassName(element, name: string): List<any> { throw _abstract(); }
|
||||
getElementsByTagName(element, name: string): List<any> { throw _abstract(); }
|
||||
classList(element): List<any> { throw _abstract(); }
|
||||
|
@ -10,13 +10,24 @@ class Html5LibDomAdapter implements DomAdapter {
|
||||
setRootDomAdapter(new Html5LibDomAdapter());
|
||||
}
|
||||
|
||||
hasProperty(element, String name) {
|
||||
// This is needed for serverside compile to generate the right getters/setters...
|
||||
return true;
|
||||
}
|
||||
|
||||
void setProperty(Element element, String name, Object value) => throw 'not implemented';
|
||||
|
||||
getProperty(Element element, String name) => throw 'not implemented';
|
||||
|
||||
invoke(Element element, String methodName, List args) => throw 'not implemented';
|
||||
|
||||
logError(error) {
|
||||
stderr.writeln('${error}');
|
||||
}
|
||||
|
||||
@override
|
||||
final attrToPropMap = const {
|
||||
'innerHtml': 'innerHtml',
|
||||
'innerHtml': 'innerHTML',
|
||||
'readonly': 'readOnly',
|
||||
'tabindex': 'tabIndex',
|
||||
};
|
||||
@ -184,11 +195,6 @@ class Html5LibDomAdapter implements DomAdapter {
|
||||
throw 'not implemented';
|
||||
}
|
||||
clone(node) => node.clone(true);
|
||||
|
||||
hasProperty(element, String name) {
|
||||
// This is needed for serverside compile to generate the right getters/setters...
|
||||
return true;
|
||||
}
|
||||
getElementsByClassName(element, String name) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
@ -26,6 +26,20 @@ function _notImplemented(methodName) {
|
||||
export class Parse5DomAdapter extends DomAdapter {
|
||||
static makeCurrent() { setRootDomAdapter(new Parse5DomAdapter()); }
|
||||
|
||||
hasProperty(element, name: string) { return _HTMLElementPropertyList.indexOf(name) > -1; }
|
||||
// TODO(tbosch): don't even call this method when we run the tests on server side
|
||||
// by not using the DomRenderer in tests. Keeping this for now to make tests happy...
|
||||
setProperty(el: /*element*/ any, name: string, value: any) {
|
||||
if (name === 'innerHTML') {
|
||||
this.setInnerHTML(el, value);
|
||||
} else {
|
||||
el[name] = value;
|
||||
}
|
||||
}
|
||||
// TODO(tbosch): don't even call this method when we run the tests on server side
|
||||
// by not using the DomRenderer in tests. Keeping this for now to make tests happy...
|
||||
getProperty(el: /*element*/ any, name: string): any { return el[name]; }
|
||||
|
||||
logError(error) { console.error(error); }
|
||||
|
||||
get attrToPropMap() { return _attrToPropMap; }
|
||||
@ -268,7 +282,6 @@ export class Parse5DomAdapter extends DomAdapter {
|
||||
return newParser.parseFragment(serialized).childNodes[0];
|
||||
}
|
||||
}
|
||||
hasProperty(element, name: string) { return _HTMLElementPropertyList.indexOf(name) > -1; }
|
||||
getElementsByClassName(element, name: string) {
|
||||
return this.querySelectorAll(element, "." + name);
|
||||
}
|
||||
|
Reference in New Issue
Block a user