我在SDK 0.7.3.1_r27487中升级dart编辑器后遇到错误“删除不允许的属性”。
我有一个自定义标签,该模板包含boostarp属性“data-target”和“data-toggle”。它在先前版本下工作,但在升级后遇到错误。
控制台
Removing disallowed attribute <A data-toggle="dropdown">
Removing disallowed attribute <BUTTON data-target=".navbar-collapse">
Removing disallowed attribute <BUTTON data-toggle="collapse">
.html代码
<element extends="div" name="x-navbar" constructor="Navbar">
<template>
..
<a name="top" href="#" class="dropdown-toggle" data-toggle="dropdown">Shop <b class="caret"></b></a>
..
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"></button>
</template>
<script type="application/dart" src="custom_ui.dart"></script>
</element>
答案 0 :(得分:8)
您可能正在使用Element.innerHtml。您应该使用Element.setInnerHtml代替。
正如您可以看到这个新方法的参数,HTML代码现在已经过验证和过滤。要恢复旧行为,您必须提供允许所有属性的验证程序或树清理程序。
明确允许锚点和按钮上的“数据”:
// Call NodeValidatorBuilder.allowX() methods to customize the validator.
final NodeValidatorBuilder _htmlValidator=new NodeValidatorBuilder.common()
..allowElement('a', attributes: ['data-target', 'data-toggle'])
..allowElement('button', attributes: ['data-target', 'data-toggle']);
query('#anElement').setInnerHtml('a content', validator: _htmlValidator);
Element
和CustomElement
类在多个位置使用HTML清理(Element.html
工厂,innerHtml
属性,createFragment
方法......)。
即使您不在自己的代码中直接使用这些方法,它们也会被底层Dart库调用(CustomElement
类是为Polymer
库创建的,但也被最新版本使用Web UI
图书馆)。
目前,无法全局禁用或自定义默认清理规则。所以我猜你必须处理setInnerHtml
次调用......或者等待另一个SDK版本来解决问题(“data-”属性是有效的HTML5代码,但默认的清理过滤器不允许它们以及内联样式:为什么这些属性被认为是不安全的?)。
注意:您应该将switching from Web UI to Polymer视为Web UI is now deprecated。
答案 1 :(得分:2)
对于那些使用有角飞镖的人,您必须使用自定义验证重新实现NgDirective:
library ng_bind_html_unsafe;
import 'dart:html' as dom;
import 'package:angular/angular.dart';
@NgDirective(
selector: '[ng-bind-html-unsafe]',
map: const {'ng-bind-html-unsafe': '=>value'} )
class NgBindHtmlUnsafeDirective{
final dom.Element element;
NgBindHtmlUnsafeDirective(this.element);
set value(value) => element.setInnerHtml(value == null ? '' : value.toString(),
validator: new dom.NodeValidatorBuilder()
..allowHtml5()
..allowElement('a', attributes: ['href'])
..allowElement('img', attributes: ['src']));
}
在那个具体的例子中,我允许链接和图片没有任何消毒,你可以扩展它,但是你想要。
答案 2 :(得分:2)
在Angular 0.9.9中ng-bind-html
支持自定义NodeValidators。
只需注册一个返回自定义NodeValidator
的工厂,如其他答案所示
factory(NodeValidator, (Injector inj) => getNodeValidator());
和ng-bind-html
将使用此NodeValidator。
我发现Angular不处理以这种方式包含的HTML(忽略任何指令/组件/表达式)。
当我需要这个时,我使用@mabounassif所示的自定义bind-html指令,在value
element.setInnerHtml
setter中使用此附加代码
if(value != null) {
_compiler(_element.childNodes, _directiveMap)(_injector, _element.childNodes);
}
答案 3 :(得分:1)
我想将 img
元素与 innerHtml
一起使用,但发现上述答案不完整。它缺少默认为相同来源的 uriPolicy
。定义自定义 UriPolicy 为我解决了这个问题。
class DefaultUriPolicy implements UriPolicy {
DefaultUriPolicy();
bool allowsUri(String uri) {
// Return true/false based on uri comparison
return true;
}
}
定义验证器如下:
allowElement('img',
attributes: ['src'], uriPolicy: new DefaultUriPolicy()))
答案 4 :(得分:0)
以@mabounassif的answer为例,我还进行了以下操作以允许链接到其他站点:
import 'dart:html' as dom;
import 'package:angular/angular.dart';
@Directive(selector: '[html-inseguro]')
class HtmlInseguro {
final dom.Element element;
final dom.NodeValidatorBuilder _validador;
HtmlInseguro(this.element)
: _validador = dom.NodeValidatorBuilder()
..allowHtml5()
..allowElement('a', attributes: ['href'], uriPolicy: _TodoUriPolicy())
..allowElement('img',
attributes: ['src'], uriPolicy: _TodoUriPolicy());
@Input('html-inseguro')
set htmlInseguro(String value) {
element.setInnerHtml(value?.toString() ?? '', validator: _validador);
}
}
class _TodoUriPolicy implements dom.UriPolicy {
@override
bool allowsUri(String uri) {
return true;
}
}
然后在组件中应该像这样:
@Component(
template: '''
<div class="vista-previa-mensaje" [html-inseguro]="mensajeAEnviar | dataReplacer: reemplazos | md2html"></div>
''',
directives: [
HtmlInseguro,
],
pipes: [Md2Html, DataReplacer])
class YourComponent{
//...
答案 5 :(得分:0)
对于想要使用 setInnerHtml
并希望允许所有标签和属性的任何人,您可以使用此验证器:
class AllowAll implements NodeValidator {
@override
bool allowsAttribute(Element element, String attributeName, String value) {
return true;
}
@override
bool allowsElement(Element element) {
return true;
}
}
用法:
element.setInnerHtml(
value,
validator: AllowAll()
);