- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
又名如何在访问自定义元素方法时绕过或避免不允许在 Angular 表达式中引用 DOM 节点
。
所以我正在使用 David Shapiro 的小型库 angular-custom-element尝试自定义元素等功能,以保证我们的组件面向 future 。我已经走了很远了,他们似乎已经注册了。但是,在示例中,它尝试在指令示例中的 ng-click 内调用元素的成员函数。
template: '<div ng-click="el.elementMethod()">{{ el.propertyNameOne }} CUSTEM ELEMENT CLICK ME</div>',
下面是完整的代码和可运行的片段。在您单击“自定义元素”之前,它不会引发错误
我尝试在方法中添加“return true”来绕过其他帖子建议的安全性,但无济于事。是否有替代实现?
angular.module('appy', []);
angular.module('appy.elementDirectives', ['customElements']);
var app = angular.module('appy', [
'appy',
'appy.elementDirectives'
]);
app.config( function($customElementsProvider ) {
'use strict';
var definitions = [
{
name: 'shiny-button',
definition: {
parent: HTMLButtonElement,
properties: {
propertyNameOne: {
get: function () {
// do any value calculations
var valueVar = 'testFooValue';
return valueVar;
},
set: function (val) {
// do any value calculations
val = val + 'X';
return val;
},
attribute: {
name: 'property-one'
}
},
propertyNameTwo: {
attribute: {},
value: 'hello',
readOnly: true
},
booleanProperty: {
attribute: {
name: 'bool-prop',
// note that "true" here just signifies that the attr should
// treated as a boolean,
boolean: true // default is false
},
value: true // default is false
}
},
// In all callbacks "this" referes to the element instance
callbacks: {
created: function () {
console.log('created')
},
// is called when the element is inserted into the DOM
attached: function () {
console.log('attached')
},
// is called when the element is removed from the DOM
detached: function () {
// include any cleanup logic
console.log('detached')
},
// called upon any attribute change including attr set programatically
// during element instantiation (but not if the elem already exists in markup)
attributeChanged: function (attr, oldVal, newVal) {
console.log('attributeChanged', attr, oldVal, newVal)
}
},
members: {
elementMethod: function (args) {
alert("member click");
console.log('clicked member');
return true;
},
memberNameOne: {
get: function (val) {
return val;
},
set: function (val) {
val = val + 'X';
return val;
},
value: 'blah blah',
readOnly: true
}
}
}
}];
console.log("Register Element");
//$customElementsProvider.register( 'shiny-button', definitions[0].definition );
$customElementsProvider.registerCollection(definitions);
});
app.controller('MainCtrl', function($scope) {
var that = this;
$scope.showTest = true;
$scope.testButtonClick = function(){
alert("testButton click")
}
});
app.directive('shinyButton', function($customElements) {
return {
restrict:'E',
scope: {
nothingHereYet: '=propertyNameOne'
},
replace: false,
template: '<div ng-click="el.elementMethod()">{{ el.propertyNameOne }} CUSTEM ELEMENT CLICK ME</div>',
controllerAs:'shinyCtrl',
// 3.4 at a minimum inject $scope and $element into your controller
controller: function($scope, $element, $attrs, $document, $log){
// 4. This is the only line of code that is required.
// this command takes care of binding all custom properties
// to the $scope including triggering a $digest() when
// any custom property is changed outside of Angular
// After this line you can enjoy the full power of AngularJS
// when interacting with your Custom Element
$customElements.$watchElement($scope, $element);
$document.on('member:changed', function(evt){
if(evt.detail.propName == 'a protopype prop we need to watch'){
// i.e. $scope.el.__proto__.memberNameOne
$scope.$digest();
}
});
// 4.2
// bind to an event on the element
// since all prop changes generate a change event
// other frameworks in the page can import and react
// to the same component
$element.on('prop:changed', function(evt){
$log.log(evt.detail);
$scope.$emit(evt.detail);
});
// 4.3
// gets the original custom elem config obj mostly for any debug
var info = $customElements.info($element);
//$customElements.$importElement($scope, $element, ['array','of','property','names']);
},
link: function(scope, iElement, iAttrs, controller){
// ...
}
};
});
/*! (C) WebReflection Mit Style License */
/*
* AngularCustomElement
* https://github.com/dgs700/angular-custom-element
* Version: 0.2.0 - 2014-11-01
* License: MIT
*/
/* Requires a Custom Element polyfill for all browsers other than Chrome
Recommended: https://github.com/WebReflection/document-register-element */
/*! (C) WebReflection Mit Style License */
(function(e,t,n,r){"use strict";function q(e,t){for(var n=0,r=e.length;n<r;n++)J(e[n],t)}function R(e){for(var t=0,n=e.length,r;t<n;t++)r=e[t],$(r,c[z(r)])}function U(e){return function(t){g.call(L,t)&&(J(t,e),q(t.querySelectorAll(h),e))}}function z(e){var t=e.getAttribute("is");return d.call(l,t?t.toUpperCase():e.nodeName)}function W(e){var t=e.currentTarget,n=e.attrChange,r=e.prevValue,i=e.newValue;t.attributeChangedCallback&&e.attrName!=="style"&&t.attributeChangedCallback(e.attrName,n===e.ADDITION?null:r,n===e.REMOVAL?null:i)}function X(e){var t=U(e);return function(e){t(e.target)}}function V(e,t){var n=this;O.call(n,e,t),B.call(n,{target:n})}function $(e,t){N(e,t),I?I.observe(e,_):(H&&(e.setAttribute=V,e[i]=F(e),e.addEventListener(u,B)),e.addEventListener(o,W)),e.createdCallback&&(e.created=!0,e.createdCallback(),e.created=!1)}function J(e,t){var n,r=z(e),i="attached",s="detached";-1<r&&(C(e,c[r]),r=0,t===i&&!e[i]?(e[s]=!1,e[i]=!0,r=1):t===s&&!e[s]&&(e[i]=!1,e[s]=!0,r=1),r&&(n=e[t+"Callback"])&&n.call(e))}if(r in t)return;var i="__"+r+(Math.random()*1e5>>0),s="extends",o="DOMAttrModified",u="DOMSubtreeModified",a=/^[A-Z][A-Z0-9]*(?:-[A-Z0-9]+)+$/,f=["ANNOTATION-XML","COLOR-PROFILE","FONT-FACE","FONT-FACE-SRC","FONT-FACE-URI","FONT-FACE-FORMAT","FONT-FACE-NAME","MISSING-GLYPH"],l=[],c=[],h="",p=t.documentElement,d=l.indexOf||function(e){for(var t=this.length;t--&&this[t]!==e;);return t},v=n.prototype,m=v.hasOwnProperty,g=v.isPrototypeOf,y=n.defineProperty,b=n.getOwnPropertyDescriptor,w=n.getOwnPropertyNames,E=n.getPrototypeOf,S=n.setPrototypeOf,x=!!n.__proto__,T=n.create||function K(e){return e?(K.prototype=e,new K):this},N=S||(x?function(e,t){return e.__proto__=t,e}:w&&b?function(){function e(e,t){for(var n,r=w(t),i=0,s=r.length;i<s;i++)n=r[i],m.call(e,n)||y(e,n,b(t,n))}return function(t,n){do e(t,n);while(n=E(n));return t}}():function(e,t){for(var n in t)e[n]=t[n];return e}),C=S||x?function(e,t){g.call(t,e)||$(e,t)}:function(e,t){e[i]||(e[i]=n(!0),$(e,t))},k=e.MutationObserver||e.WebKitMutationObserver,L=(e.HTMLElement||e.Element||e.Node).prototype,A=L.cloneNode,O=L.setAttribute,M=t.createElement,_=k&&{attributes:!0,characterData:!0,attributeOldValue:!0},D=k||function(e){H=!1,p.removeEventListener(o,D)},P=!1,H=!0,B,j,F,I;k||(p.addEventListener(o,D),p.setAttribute(i,1),p.removeAttribute(i),H&&(B=function(e){var t=this,n,r,s;if(t===e.target){n=t[i],t[i]=r=F(t);for(s in r){if(!(s in n))return j(0,t,s,n[s],r[s],"ADDITION");if(r[s]!==n[s])return j(1,t,s,n[s],r[s],"MODIFICATION")}for(s in n)if(!(s in r))return j(2,t,s,n[s],r[s],"REMOVAL")}},j=function(e,t,n,r,i,s){var o={attrChange:e,currentTarget:t,attrName:n,prevValue:r,newValue:i};o[s]=e,W(o)},F=function(e){for(var t,n,r={},i=e.attributes,s=0,o=i.length;s<o;s++)t=i[s],n=t.name,n!=="setAttribute"&&(r[n]=t.value);return r})),t[r]=function(n,r){y=n.toUpperCase(),P||(P=!0,k?(I=function(e,t){function n(e,t){for(var n=0,r=e.length;n<r;t(e[n++]));}return new k(function(r){for(var i,s,o=0,u=r.length;o<u;o++)i=r[o],i.type==="childList"?(n(i.addedNodes,e),n(i.removedNodes,t)):(s=i.target,s.attributeChangedCallback&&i.attributeName!=="style"&&s.attributeChangedCallback(i.attributeName,i.oldValue,s.getAttribute(i.attributeName)))})}(U("attached"),U("detached")),I.observe(t,{childList:!0,subtree:!0})):(t.addEventListener("DOMNodeInserted",X("attached")),t.addEventListener("DOMNodeRemoved",X("detached"))),t.addEventListener("readystatechange",function(e){q(t.querySelectorAll(h),"attached")}),t.createElement=function(e,n){var r,i=M.apply(t,arguments);return n&&i.setAttribute("is",e=n.toLowerCase()),r=d.call(l,e.toUpperCase()),-1<r&&$(i,c[r]),i},L.cloneNode=function(e){var t=A.call(this,!!e),n=z(t);return-1<n&&$(t,c[n]),e&&R(t.querySelectorAll(h)),t});if(-1<d.call(l,y))throw new Error("A "+n+" type is already registered");if(!a.test(y)||-1<d.call(f,y))throw new Error("The type "+n+" is invalid");var i=function(){return t.createElement(p,u&&y)},o=r||v,u=m.call(o,s),p=u?r[s]:y,g=l.push(y)-1,y;return h=h.concat(h.length?",":"",u?p+'[is="'+n.toLowerCase()+'"]':p),i.prototype=c[g]=m.call(o,"prototype")?o.prototype:T(L),q(t.querySelectorAll(h),"attached"),i}})(window,document,Object,"registerElement");
/*
* AngularCustomElement
* https://github.com/dgs700/angular-custom-element
* Version: 0.2.0 - 2014-11-01
* License: MIT
*/
!function(){"use strict";function a(){function a(a,b){function c(a){var b=parseFloat(a);return!isNaN(b)&&isFinite(b)?b:a}function e(a,b,c,d,e,f){if(!c)return b;c.setterCalled[e]=!0;try{e&&f?b?c.setAttribute(e,""):c.removeAttribute(e):e&&c.setAttribute(e,b),c.onPropChange(b)}catch(g){}return d=f?!!c[a]:c[a],c.propChangeNotify(c,a,b,d,e,"prop:changed"),b}if("string"!=typeof a||!/.*-.*/.test(a))return console.error("Invalid element name: ",a),this;if(a=a.toLowerCase(),d[a])return this;var f=b.parent?b.parent.prototype:b["extends"]?Object.create(document.createElement(b["extends"]).constructor).prototype:HTMLElement.prototype,g=b["extends"]||null,h=b.properties||{},i=b.members||{},j={prototype:{}},k=function(){};for(var l in i)!function(a,b){function c(a,b,c){return document.dispatchEvent(new CustomEvent("member:changed",{detail:{propName:c,newValue:a,oldValue:b||null}})),a}var d,e,f,g,h,i,l=this;"function"==typeof b[a]?j.prototype[a]={enumerable:!0,value:b[a]}:(d=b[a],i=d.readOnly||!1,g=d.value||null,e="function"==typeof d.get?function(){return g=d.get.call(l,g)}:function(){return g},f=i?k:"function"==typeof d.set?function(b){b=d.set.call(l,b),h=this[a]||null,g=c(b,h,a)}:function(b){h=this[a]||null,g=c(b,h,a)},j.prototype[a]={get:e,set:f,enumerable:!0})}(l,i);j.prototype.registerCallback={value:function(a,b){a.onPropChange=b},enumerable:!0},j.prototype.propChangeNotify={value:function(a,b,c,d,e,f){a.dispatchEvent(new CustomEvent(f,{detail:{propName:b,newValue:c,oldValue:d,attrName:e||null}}))},enumerable:!0},j.prototype.definition={value:b};var m,n=b.callbacks||{},o=n.created||k,p=n.attached||k,q=n.detached||k,r=n.attributeChanged||k,s={},t=[];for(m in h)!function(a,b){t.push(function(d){var f,g,h,i,l,m,n,o,p;o=!1,l=null,g=null,f=b[a],n=f.readOnly||!1,p=f.attribute?!0:!1,o=p&&f.attribute.boolean?!0:!1,p&&!n&&d?(g=f.attribute.name?f.attribute.name:a.toLowerCase(),s[g]={name:a,bool:o},o?l=d.hasAttribute(g)?!0:f.value?!0:!1:(l=d.hasAttribute(g)?d.getAttribute(g):f.value?f.value:null,l=c(l)),d.hasAttribute(g)||(o&&l?d.setAttribute(g,""):o?d.removeAttribute(g):d.setAttribute(g,l)),d.setterCalled[g]=!1):o&&!d?l=f.value?!0:!1:(l=f.value?f.value:null,l=c(l)),h="function"==typeof f.get?f.get:function(){return l},i=n?k:"function"==typeof f.set?function(b){b=f.set.call(d,b),b=e(a,b,d,m,g,o),l=b}:function(b){l=e(a,b,d,m,g,o)},d?Object.defineProperty(d,a,{get:h,set:i,enumerable:!0,configurable:!0}):j.prototype[a]={get:h,set:i,enumerable:!0}})}(m,h),t.forEach(function(a){a.call(this,null)});j.prototype.createdCallback={enumerable:!0,value:function(){this.setterCalled={};var a=this;t.forEach(function(b){b.call(a,a)});var b=o?o.apply(this,arguments):null;return b}},j.prototype.attributeChangedCallback={enumerable:!0,value:function(a,b,d){if(s[a]&&!this.setterCalled[a]){var e=s[a];e.bool&&""===d&&(d=!0),this.setterCalled[a]=!1,this[e.name]=e.bool?!!d:c(d)}var f=r?r.apply(this,arguments):null;return f}},j.prototype.attachedCallback={enumerable:!0,value:function(){this.classList.remove("unresolved");var a=p?p.apply(this,arguments):null;return a}},j.prototype.detachedCallback={enumerable:!0,value:function(){var a=q?q.apply(this,arguments):null;return a}};var u={prototype:Object.create(f,j.prototype)};return g&&(u["extends"]=g),d[a]=document.registerElement(a,u),this}function b(a){return Array.isArray(a)?(a.forEach(function(a){var b=a.name,c=a.definition;return"string"!=typeof b||c!==Object(c)?(console.warn("bad element definition format"),!1):void e.register(b,c)}),!0):(console.error("parameter to registerCollection must be an array"),!1)}function c(){return{info:function(a){return a[0].__proto__.definition},$watchElement:function(a,b,c){c=c||!1,a.el=b[0],c||a.el.registerCallback(a.el,function(){return setTimeout(function(){a.$digest()},0),!0})},$importElement:function(a,b,c,d){var e=null,f=null;return Array.isArray(c)&&(c.forEach(function(a,b,c){c[b]=c[b].toLowerCase()}),e=new MutationObserver(function(b){b.forEach(function(b){-1!==c.indexOf(b.attributeName)&&a.$digest()})}).observe(b[0],{attributes:!0,childList:!0,characterData:!0,attributeOldValue:!0})),d&&(f=b.addEventListener(d,function(){a.$digest()})),Array.isArray(c)&&d?{observer:e,eventBinding:f}:!1}}}var d={};window.registeredElements=this.registeredElements=d,this.register=a;var e=this;this.registerCollection=b,this.$get=c,c.$inject=["$window"]}angular.module("customElements",["ng"]).provider("$customElements",a)}(window);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html ng-app="appy">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<link data-require="bootstrap-css@*" data-semver="3.2.0" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js@1.2.x" src="https://code.angularjs.org/1.2.6/angular.js" data-semver="1.2.25"></script>
<script src="angular-custom-element.js"></script>
</head>
<body ng-controller="MainCtrl as vm">
<shiny-button>this will be replaced by directive template</shiny-button>
<br/><br/>
<div ng-show="showTest" ng-click="testButtonClick()">Test Click Div</div>
</html>
最佳答案
这是因为 AngularJS 1.x 尚不支持 Web 组件友好。它假设如果您直接从 Angular 宇宙中引用 DOM 属性,那么您一定是愚蠢的,因为该代码可能是恶意的,或者它只是违反了 Angular 代码应该完全封装于外部世界并且框架处理所有外部的原始概念。相互作用。虽然在大多数情况下确实如此,但它是在我们知道自定义元素很快将成为我们构建可重用 UI Web 组件的方式的核心之前出现的。
在 NG 2.0 之前,您可能需要执行以下操作:
替换这个:
<div ng-click="el.elementMethod()">
这样:
<div ng-click="callMember()">
$scope.callMember = function(){
$scope.el.elementMethod();
};
使用替换代码没有错误。
有趣的是,通过 {{ el.propertyNameOne }}
进行相同的 DOM 访问不会导致 Angular 抛出相同的错误。想想吧。
关于javascript - 如何在单击时调用自定义元素成员方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27554992/
我在选项卡中有我的网络应用程序的选项。 aaa bbb ccc ddd eee 当用户单击任何选项卡(在同一窗口中)时,我会使用此代码获得淡出效果,然后自动
如何获得一个简单的调用单击来实现如下功能:http://jsfiddle.net/ftwPS/6/我显然错过了一些基本的东西,因为当您单击“CLICK”时这不起作用。 $('tr').click(fu
我有一个列表,在左侧显示一个插入符号图标,单击它时应该更改图标。每当我单击一个图标时,所有图标都会更改。 detailedInfo = []; subordinateInfo; openSu
我有一个 div,我想对其进行设置,以便当我单击其他内容时,它会隐藏该 div。 我也是这样 $('body').click(function(){ if(loginOpened) {
我有很多装有不同内容的盒子。 如果单击第一个框,您可以看到一个包含更多详细信息的弹出框。如果单击第二个、第三个等框,您必须查看这些框的详细信息。 我的问题:如果我点击框号。 2 我看到了盒子号的详细信
当我点击 .add-btn 时,我将 .add-btn 的样式更改为 background:#cccccc 并将 val() 更改为“-”。 现在当我用 tr td .list 删除添加的文本时,它是
感谢 SO 的出色贡献者!当您开始了解 jQuery 时,它会变得更酷。 :) 所以我有一个 LI,单击时会显示/隐藏子 UL。我想做的是能够单击 LI 内的链接,打开一个空白窗口,但也不会关闭子 U
我有这份文档,它使我能够获得一份带有点击进度的多项选择选择调查问卷。 如何用图像代替此处的文字? (并且仍然有这样的机制,一旦单击[图像],就会提出下一个问题) 我已经尝试使用 UL/H1 设置背景图
我想在 JQGrid 的刷新按钮单击上编写代码。有什么事件吗? 最佳答案 如果您需要在开始刷新之前执行一些操作,您应该使用 beforeRefresh打回来: $("#grid_id").jqGrid
问题是将对象或多个参数从模板传递到组件,并使用它们将数据添加到 API。 任务.service.ts addTasks(task: Task): Observable{ let headers =
我有一个像这样的primefaces选项卡 View : This tab has static content. this t
我在 jquery 中有一个有效的 a.click() 函数...但是如果我单击一个 anchor ,我会打开一个新窗口...但是我怎样才能阻止浏览器本身打开一个新窗口? 示例: $('a')
有没有简单的方法来创建代码:如果 URL 更改或单击链接显示 div(例如加载 gif 3 秒),则显示页面?有点像空白的白色页面,加载 gif 旋转 3 秒然后显示页面? 谢谢! 最佳答案 给定 G
我需要知道此时按钮的状态是否被点击? 谢谢 最佳答案 if (myButton.state & UIControlStateHighlighted) { // Do your stuff the
我正在 NSImageView 上绘制一条 NSBezierPath 线。我正在创建 NSBezierPath 对象,设置 moveToPoint,设置 lineToPoint,设置 setLineW
我的 Selenium 代码存在问题,无法正确执行按键 + 单击操作。 测试应打开 jqueryui.com 链接并选择页面上的前 2 个 li 元素。 我正在使用 Selenium 2.23 和 F
单击时我将更改字符串一部分的样式。例如“TEXT”,然后单击“T”,之后它会将样式从黑色更改为红色,仅 T在我的代码中,当我单击文本时,我拆分文本并保留在“split”数组中,它将调用handleCl
我在网站上有一个 anchor 。当有人点击它时,我在 jquery 中执行一些操作并更改名称,但是当再次单击它时,事件被触发,尽管我已经更改了它的名称。代码在这里: $(".like_cont a[
我有一个下载链接Download我希望每次当有人点击“下载”时,我都可以将其插入数据库total_downloads+1。为了插入数据库,我通常使用 然后 if (isset($_POST['d
我是一名优秀的程序员,十分优秀!