Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/379.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何编写通过选择器切换类的角度指令_Javascript_Angularjs_Angularjs Directive - Fatal编程技术网

Javascript 如何编写通过选择器切换类的角度指令

Javascript 如何编写通过选择器切换类的角度指令,javascript,angularjs,angularjs-directive,Javascript,Angularjs,Angularjs Directive,我试图编写一个指令,根据选择器条件切换类: <label class-when="{'is-checked': ':has(input:checked)', 'is-disabled': ':has(input:disabled)'}"> <input type="checkbox"> Example checkbox </label> 好的,在读了你的赏金评论后,我知道你希望这是独立于控制器的。我花了一些时间彻底修改了我的解决方案,我想我终

我试图编写一个指令,根据选择器条件切换类:

<label class-when="{'is-checked': ':has(input:checked)', 'is-disabled': ':has(input:disabled)'}">
    <input type="checkbox">
    Example checkbox
</label>

好的,在读了你的赏金评论后,我知道你希望这是独立于控制器的。我花了一些时间彻底修改了我的解决方案,我想我终于找到了一种方法来实现你想要的

这实际上归结为两件事:

1) 检测复选框
上的更改:选中状态,以及

2) 检测复选框
:禁用状态的更改

检测
1)
很容易,因为您可以使用简单的jQuery更改处理程序,但是检测
2)
需要更多的研究。它需要在子
ng disabled
属性上使用
scope.$watch

下面是如何工作的演示:

var-app=angular.module(“myApp”,[])
.directive(“classWhen”,function(){
函数集合类(classWhen,$element,$input){
Object.key(classWhen).forEach(function(key){
var测试=classWhen[键];
//.toggleClass(“类名”,true)==.addClass(“类名”)
//.toggleClass(“类名”,false)==.removeClass(“类名”)
$element.toggleClass(键,$element.is(测试));
});
}
返回{
限制:“A”,
链接:功能链接(范围、元素、属性){
var classWhen=JSON.parse(attrs.classWhen);
变量$element=$(element);
$element.find(“*”).each(函数(索引,元素){
变量$elem=$(本);
//命名更改事件的名称空间,以便我们可以轻松地对其执行.off()
$elem.off(“change.classWhen”);
$elem.on(“change.classWhen”,函数(){
setClasses(classWhen,$element,$elem);
});
//监视禁用属性的子对象
范围:$watch($elem.attr(“ng禁用”),功能(val){
setClasses(classWhen,$element,$elem);
});
});
}
};
});
已选中
{
背景颜色:黄色;
}
.残疾{
背景颜色:浅蓝色;
}

禁用所有


示例复选框1
示例复选框2

示例复选框3
示例复选框4
以下是我尝试以通用方式解决您的问题的方法:

指令代码:

app.directive('classWhen', () => (scope, element, attrs) => {
  scope.$watchCollection(getClasses, setClasses)

  function getClasses() {
    // We have to evaluate expression in attrs.classWhen so that we get object
    const rawClasses = scope.$eval(attrs.classWhen)
    const classes = {}

    // then we normalize it so that strings are treated as jquery selectors
    Object.keys(rawClasses).forEach((className) => {
      const expr = rawClasses[className]
      classes[className] = typeof expr === 'string'
        ? element.is(expr)
        : !!expr // we normalize falsy values to booleans
    })

    // then we return it to $watchCollection
    return classes
  }

  /**
   * will be called whenever any of the classes changes
   */
  function setClasses(classes) {
    Object.keys(classes).forEach((className) => {
      element.toggleClass(className, classes[className])
    })
  }
})

我已经为此创建了一个通用的小提琴,还使用了您使用的RequireJS

请看这里

注意:无论您在选择器中添加了什么属性,如
:checked
:disabled
,都将相关的角度属性添加到子元素中,如
ng model
ng disabled
。它将像一个符咒一样工作

代码

var-app=window.app=angular.module(“myApp”,[]);
定义('classWhenDirective',函数(){
//var=要求('lodash');
var-app=window.app;调试器;
app.directive(“classWhen”,function()){
返回{
限制:“A”,
链接:函数(范围、元素、属性){
范围$watch(getChanges,setClasses)
函数getChanges(){
var attrs=[];
函数getAttrs(elm){
$.each(elm.attributes,function(i,attrib){
var name=attrib.name;
var值=属性值;
if(value&&name.indexOf('ng-')>-1){
值=范围$eval(值);
}
如果(值){
属性推送(名称+':'+值);
}
});
}
getAttrs(element.get(0));
element.children().each(function()){
getAttrs(本);
});
返回attrs.join(',');
}
函数setClasses(){
var rawClasses=范围$eval(attrs.classWhen);
Object.keys(类).forEach(函数(类名){
var expr=rawClasses[className]
var setClass=typeof expr=='string'
?元素is(expr)
:!!expr;
toggleClass(类名,setClass);
});
}
}
};   
});
});
定义('todo',['classWhenDirective',函数(){
var-app=window.app;
app.controller('myController',函数($scope){
});
});
//角自举
require(['todo',function()){
引导(文档,['myApp']);
});
已选中
{
颜色:绿色;
}
.残疾{
颜色:灰色;
}

ClassWhen指令
禁用所有


ClassWhen复选框1
ClassWhen复选框2
@ryanyuyu我假设由于父元素上的结构指令或元素本身(在提供的代码中没有显示)而需要一个指令。我可能错了,虽然我已经为您解决了一个主要问题,那就是您的
scope.object
是一个字符串,因此执行
\uuu.forOwn()。要解决这个问题,您需要在
scope.object
上执行
JSON.parse()
,这将导致下一个问题。您的字符串是无效的JSON,因为它在属性/值周围有单引号,并且需要双引号才能成为有效的JSON。问题仍然是,当用户选中/取消选中复选框时,您的指令不会触发。我仍在研究这一部分,但我认为我已经向正确的方向迈出了一大步,或者只是对scope.object使用双向
“=”
绑定。从角度来看,所有这些都是错误的。你不应该做这样的事。如果您希望容器样式依赖于输入-指令应该在每个输入元素上,而不是在顶部有一个魔术指令。@ryanve检查我的更新solution@ryanve它能解决你的问题吗?如何改进我的答案?我喜欢这种方法的简单性,但取决于DOM如何更改,这需要几秒钟的时间。就像它在等待下一个摘要一样,这个解决方案的问题与我的一个原始解决方案相同(如果您查看我答案上的编辑历史记录)#是的
app.directive('classWhen', () => (scope, element, attrs) => {
  scope.$watchCollection(getClasses, setClasses)

  function getClasses() {
    // We have to evaluate expression in attrs.classWhen so that we get object
    const rawClasses = scope.$eval(attrs.classWhen)
    const classes = {}

    // then we normalize it so that strings are treated as jquery selectors
    Object.keys(rawClasses).forEach((className) => {
      const expr = rawClasses[className]
      classes[className] = typeof expr === 'string'
        ? element.is(expr)
        : !!expr // we normalize falsy values to booleans
    })

    // then we return it to $watchCollection
    return classes
  }

  /**
   * will be called whenever any of the classes changes
   */
  function setClasses(classes) {
    Object.keys(classes).forEach((className) => {
      element.toggleClass(className, classes[className])
    })
  }
})