Javascript 如何生成自定义标签单选按钮的指令

Javascript 如何生成自定义标签单选按钮的指令,javascript,jquery,angularjs,Javascript,Jquery,Angularjs,以下是一个自定义单选按钮: HTML代码: <div ng-app="app"> <div ng-controller="ctrl" class="sm-box"> <p>Please select a mode: <sm-radio model="mode" value="MODE1" label="One" ng-click='mode="MODE1"'></sm-radio> <s

以下是一个自定义单选按钮:

HTML代码:

<div ng-app="app">
   <div ng-controller="ctrl" class="sm-box">
      <p>Please select a mode:
      <sm-radio model="mode" value="MODE1" label="One" ng-click='mode="MODE1"'></sm-radio>
      <sm-radio model="mode" value="MODE2" label="Two"></sm-radio>
      <sm-radio model="mode" value="MODE3" label="Three"></sm-radio></p>
      <p>Selected mode is: {{mode}}</p>
   </div>
</div>

请选择一种模式:

所选模式为:{{mode}

相应的JavaScript:

var app = angular.module('app', []);

app.controller('ctrl', ['$scope', function( $scope ) {
   $scope.mode = 'MODE1';
}]);

app.directive('smRadio',  ['$compile', function($compile) {
   return {
      restrict: 'E',
      template: function( tElt, tAttrs ) {
         tElt.addClass( 'sm-radio' );
         tElt.append(
            '<input type="radio"' +
            ' name="'     + tAttrs.model + '"' +
            ' ng-model="' + tAttrs.model + '"' +
            ' value="'    + tAttrs.value + '"' +
            ' /><label>'  + tAttrs.label + '</label>'
         );
         if( ! tElt.attr('ng-click')) {
            // This is a first try
            tElt.attr('ng-click', 'mode="' + tAttrs.value + '"' );
            // this is a variant
            tElt.ngClick = 'mode="' + tAttrs.value + '"';
            // None has effect...
            $compile(tElt); // compilation here had twice elements!!!
         }
      }
   };
}]);
var-app=angular.module('app',[]);
app.controller('ctrl',['$scope',函数($scope){
$scope.mode='MODE1';
}]);
app.directive('smRadio',['$compile',function($compile){
返回{
限制:'E',
模板:功能(tElt、tAttrs){
tElt.addClass(“sm无线电”);
电话附加(
''+tAttrs.label+''
);
如果(!tElt.attr('ng-click')){
//这是第一次尝试
tElt.attr('ng-click','mode=“”+tAttrs.value+”);
//这是一种变体
tElt.ngClick='mode=“”+tAttrs.value+'”;
//没有一个是有效的。。。
$compile(tElt);//这里的编译有两个元素!!!
}
}
};
}]);
问题是“一”是可点击的,并将模型“模式”设置为“模式1”,但“二”和“三”不是,只有单选按钮可以选择“模式2”或“模式3”

正如您在HTML源代码中看到的,第一个具有“ng click”属性,而另一个没有。我正试图通过代码在指令中添加“ng click”属性,但没有成功

如何在指令中添加“ng click”属性?


编辑:完全不使用ng点击的答案指南,因此标题已更新

使用隔离范围将值从“外部世界”传递给指令被认为是最佳做法。正如您所看到的,这也使它变得更容易:

var app = angular.module('app', []);

app.controller('ctrl', ['$scope', function( $scope ) {
   $scope.mode = 'MODE1';
}]);

app.directive('smRadio', function($compile) {
   return {
      restrict: 'E',
      scope: {
        model: '=',
        value: '@',
        label: '@'
      },

      template: '' +
        '<input type="radio" name="name" ng-model="model" value="value"' +
        ' ng-checked="model==value" ng-click="model=value">' +
        '<label ng-click="model=value">{{label}}</label>',

      compile: function(tElt) {
         tElt.addClass( 'sm-radio' );
      }
   };
});
var-app=angular.module('app',[]);
app.controller('ctrl',['$scope',函数($scope){
$scope.mode='MODE1';
}]);
应用指令('smRadio',函数($compile){
返回{
限制:'E',
范围:{
型号:'=',
值:'@',
标签:“@”
},
模板:“”+
'' +
“{label}}”,
编译:函数(tElt){
tElt.addClass(“sm无线电”);
}
};
});
下面是一个工作示例:


(如果指令的“template”属性中有这么多代码,我会将其移动到html文件之外,并使用
templateUrl
属性将其链接)

无需单击
ng即可。小提琴:

var-app=angular.module('app',[]);
app.controller('ctrl',['$scope',函数($scope){
$scope.modes=[
{标签:“模式1”,值:1},
{标签:'模式2',值:2},
{标签:'模式3',值:3}
];
$scope.selected=2;
}]);
应用指令('smRadio',函数(){
返回{
限制:'E',
作用域:{model:'=',selected:'='},
模板:功能(tElt、tAttrs){
返回“{radio.label}}”;
},
链接:功能(范围、要素、属性){
scope.change=函数(val){
scope.selected=val;
}
}
};
});

这正是我想要的,主要是受到答案的启发,简化了答案,以及用
标签
代替答案的
div
的想法

var-app=angular.module('app',[]);
app.controller('ctrl',['$scope',函数($scope){
$scope.xmode='MODE2';
$scope.ymode='MODE_B';
}]);
应用指令('smRadio',函数(){
返回{
限制:'E',
范围:{
型号:'=',
值:'@',
标签:“@”
},
模板:
'' +
“{{label}}”
};
});
.sm框{
背景颜色:浅灰色;
边框:实心1px;
填充:4px;
宽度:500px;
}
.sm收音机{
背景颜色:浅蓝色;
颜色:#fff;
显示:内联块;
边框:1px实心暗光;
边界半径:8px;
填充:8px;
}
.sm收音机>输入{
宽度:24px;
高度:24px;
垂直对齐:文本底部;
}

请选择一个Xmode:

所选模式为:{xmode}

请选择一个Y模式:

所选模式为:{ymode}


我认为您需要在tElt上使用$compile。如果从javascript端添加DOM,angular对此一无所知。这就是为什么需要$compile将其绑定到作用域。我已经尝试过编译,但效果很微妙:添加了两次元素,没有点击……谢谢。您可以在sm无线电元素上设置ng click来代替标签吗?可以,如果您不想将此功能封装在指令中,您可以在指令本身上设置它。然后,您可以在
内部元素上单击ommit
ng。当我尝试运行提供的示例时,JSBin出现了一个错误:“error”“SyntaxError:在”“error”“脚本错误处意外标记非法。(第0行)“我也想测试一下--提前感谢…@ClaireW抱歉,我的错,一定是在保存之前更改了某些内容。If现在已经修复了:我更喜欢将HTML中的标签和行为等视图内容放入控制器中。值是
{MODE1,MODE2,MODE3}
,标签是
{'1','2','3'}
。整个
div
必须是可点击的。我刚刚试过小提琴:+1来点击标签!
var app = angular.module('app', []);

app.controller('ctrl', ['$scope', function( $scope ) {
    $scope.modes = [
        {label: 'MODE 1', value: 1 },
        {label: 'MODE 2', value: 2},
        {label: 'MODE 3', value: 3}
    ];

    $scope.selected = 2;
}]);

app.directive('smRadio', function() {
   return {
      restrict: 'E',
      scope: {model: '=', selected: '='},
      template: function( tElt, tAttrs ) {
          return '<label ng-repeat="radio in model"><input type="radio" ng-value="radio.value" name="modes" ng-model="selected" ng-change="change(radio.value)">{{radio.label}}</label>';
      },
       link: function(scope, elem, attrs){
           scope.change = function(val){
               scope.selected = val;
           }
       }
   };
});