为AngularJS指令动态选项 [英] Dynamic Options for AngularJS Directive

查看:253
本文介绍了为AngularJS指令动态选项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图动态变量传递到一个显示时间选择器(pickadate.js一个指令: HTTP ://amsul.ca/pickadate.js/time/ )。不过,我奋力如何得到的选项进入指令。我走遍了互联网,但看到的方法众多,而且很困惑就如何更好地构建这个,因为它是行不通的。这是我目前的code:

指令:

  //选择作为接一个时间HTML元素的日期指示
appDirectives.directive('pickATime',函数(){
    返回{
        //限制它是在这种情况下的一个属性
        限制:'A',
        //负责注册DOM听众以及更新的DOM
        链接:功能(范围,元素,ATTRS){
            element.pickatime($范围的eval(attrs.pickATime));
        },
        范围: {
            timeOptions:'=选项'
        },
        templateUrl:../Templates/timeoptions.html
    };
});

指令模板:

 敏:{{timeOptions.startTime}}最大值:{{customerInfo.endTime}}

HTML

 <输入类型=文本占位符=开始时间ID =timestart接一时间选项=TIMERANGE数据-NG-模式=itemtimestart类=表格控自动完成=关闭>

控制器在动态传递值(存储在REST)

  //查询设置变量函数以后使用
appSettings.query(功能(设置){
    //数据是价值的对象之内,所以这推动服务器端数组变量
    VAR设置= settings.value;    //结果Foreach源,其中设置等于活动得到apporpriate变量
    angular.forEach(设置,功能(settingvalue,settingkey){
        如果(settingvalue.Title =='主动'){            //获取工作和非工作的持续时间为变量
            workDuration = settingvalue.Work_x0020_Day​​_x0020_Hours_x0020;
            nonWorkDuration = settingvalue.Non_x0020_Work_x0020_Day​​_x0020_H;            //获取$范围变量来控制时间选择范围
            变种startHour = settingvalue.Work_x0020_Day​​_x0020_Start_x0020.split(:)[0];
            变种startMinute = settingvalue.Work_x0020_Day​​_x0020_Start_x0020.split(:)[1];
            变种的startTime ='['+ startHour +','+ startMinute +']';
            变种endHour = settingvalue.Work_x0020_Day​​_x0020_End_x0020_M.split(:)[0];
            变种endMinute = settingvalue.Work_x0020_Day​​_x0020_End_x0020_M.split(:)[1];
            变种ENDTIME ='['+ endHour +','+ endMinute +']';
            $ scope.timeRange = {分钟:startTime时,最大:结束时间};
        }
    })
});

的非动态法(工作)上的输入如下:

 <输入类型=文本占位符=结束时间ID =timeend接一时间={分钟:[0,0],最大: 23,30]}数据-NG-模式=itemtimeend级=表格控自动完成=关闭>

更新:与戴维的工作,我已经调整到了以下几点。它正确地记录了TIMERANGE,但给出了一个不确定的timeOptions在指令

TIMERANGE日志:

 时开始为[8,30]时间到底是[17,0]

timeOption日志:

 时间选项登录未定义

指令(未定义的记录timeOptions):

  appDirectives.directive('pickATime',函数(){
返回{
    //限制它是在这种情况下的一个属性
    限制:'A',
    //负责注册DOM听众以及更新的DOM
    链接:功能(范围,元素,ATTRS){
        element.pickatime(scope.pickATime);
        的console.log(时间选项日志+ scope.timeOptions);
    },
    范围: {
        timeOptions:'='    },
    templateUrl:../Templates/timeoptions.html
};});

模板:

 分钟:{{timeOptions.min}},最大值:{{timeOptions.max}}

控制器(注销正确):

  //获取$范围变量来控制时间选择范围
变种startHour = settingvalue.Work_x0020_Day​​_x0020_Start_x0020.split(:)[0];
变种startMinute = settingvalue.Work_x0020_Day​​_x0020_Start_x0020.split(:)[1];
变种的startTime ='['+ startHour +','+ startMinute +']';
变种endHour = settingvalue.Work_x0020_Day​​_x0020_End_x0020_M.split(:)[0];
变种endMinute = settingvalue.Work_x0020_Day​​_x0020_End_x0020_M.split(:)[1];
变种ENDTIME ='['+ endHour +','+ endMinute +']';
$ scope.timeRange = {
    分:startTime时,
    最高要求:结束时间
};

HTML

 <输入类型=文本占位符=开始时间ID =timestart接一时间timeOptions =TIMERANGE数据-NG-模式=itemtimestart类=表格控自动完成=关闭>

更新 - 选择器工作......但现在形式不提交时间数据每本邮报:<一href=\"http://stackoverflow.com/questions/29681821/timepicker-directive-wont-submit-time-undefined\">TimePicker指令将不会提交时间(不确定) **

巨大的感谢@戴夫 - alperovich和@乔 - enzminger的不懈帮助和伟大的答案。

控制器:

  //获取$范围变量来控制时间选择范围
变种startHour = settingvalue.Work_x0020_Day​​_x0020_Start_x0020.split(:)[0];
变种startMinute = settingvalue.Work_x0020_Day​​_x0020_Start_x0020.split(:)[1];
变种endHour = settingvalue.Work_x0020_Day​​_x0020_End_x0020_M.split(:)[0];
变种endMinute = settingvalue.Work_x0020_Day​​_x0020_End_x0020_M.split(:)[1];
$ scope.timeRange = {
分:[startHour,startMinute]
最大:[endHour,endMinute]
};

指令:

  appDirectives.directive('pickATime',函数(){
返回{
    //限制它是在这种情况下的一个属性
    限制:'A',
    //负责注册DOM听众以及更新的DOM
    链接:功能(范围,元素,ATTRS){
        element.pickatime(scope.options());
    },
    范围: {
        选项​​:'和; pickATime
    },
};
});

用法:

 &LT;输入NG-IF =TIMERANGE类型=文本占位符=开始时间ID =timestart接一时间=TIMERANGE数据-NG -model =itemtimestart级=表格控自动完成=关闭&GT;


解决方案

有许多不同的方式从父范围数据传递到一个指令。您选择(正确地)之类的由孤立的范围提供选择,由指示

 范围:{
}

您的指令参数。这意味着你的指示的范围不会中典型从父范围继承。

你的第一个例子不工作的原因是该行:

  element.pickatime($范围的eval(attrs.pickATime));

最终传递未定义到element.pickatime()方法。

这是因为这行code的作用是试图评估来自你对指令的DOM在接一个时HTML属性的值包含的前pression(这是一个字符串)范围。拾取一个时间属性的值是您的第一个例子是空字符串。

当您使用非动态版,拾取一个时间属性的值现在为字符串

 {分钟:[0,0],最大:[23,30]}

这是一个有效的角度EX pression和$的eval将返回最小和最大属性中设置为[0,0]和对象[23,30]分别,所以你的指令工作。

在这两种情况下,你的指令完全忽略传递到指令与选项属性值

一个简单的办法是修改指令以使用通过选项属性传递的信息。您的指令编写方式,此对象将绑定到$ scope.timeOptions值(以后会更多)双向。从本质上讲,至$任何改变scope.timeOptions将在父范围内的财产TIMERANGE显示,反之亦然。

你的指令的变化是使用:

  element.pickatime(scope.timeOptions);

附加题:

在您的最后一个例子,你指出timeOptions是在指令中定义。这是因为在html需要是:

 &LT;输入类型=文本占位符=开始时间ID =timestart接一个按时间选择=TIMERANGE数据-NG-模式= itemtimestart级=表格控自动完成=关闭&GT;

唯一的变化是timeOptions - >时间选项

这是角柄如何约定属性scope属性映射。

额外附加题:

您的例子并不需要双向绑定(我不认为你想改变指令内的选项)。您可以通过使用与放大器避免两个$腕表创作;而不是=。这将是我对你的指令的最终版本:

  appDirectives.directive('pickATime',函数(){
    返回{
        //限制它是在这种情况下的一个属性
        限制:'A',
        //负责注册DOM听众以及更新的DOM
        链接:功能(范围,元素,ATTRS){
            element.pickatime(scope.options());
        },
        范围: {
            选项​​:'和; pickATime
        },
        templateUrl:../Templates/timeoptions.html
    };
});

使用方式:

更新点符号的问题:

在你的控制器,你需要使用点符号为itemtimestart:

  .controller('XXX',函数($范围){
    $ scope.parameters = {
    }
}&LT;输入NG-IF =TIMERANGE类型=文本占位符=开始时间ID =timestart接一时间=TIMERANGE数据-NG-模式=parameters.itemtimestart级=形式 - 控制自动完成=关闭&GT;$ scope.paramters.itemtimestart现在应该是正确的时间。

您还可以通过使用控制器语法简化了这一点。

这里是一个普拉克

I am trying to pass dynamic variables into a directive that displays a time picker (pickadate.js: http://amsul.ca/pickadate.js/time/). However, I am struggling on how to get the options into the directive. I am scoured the internet, but see a multitude of approaches, and am confused on how best to construct this as it is not working. Here is my current code:

Directive:

// Pick a date directive used as pick-a-time on HTML element
appDirectives.directive('pickATime', function() {
    return {
        // Restrict it to be an attribute in this case
        restrict: 'A',
        // responsible for registering DOM listeners as well as updating the DOM
        link: function(scope, element, attrs) {
            element.pickatime(scope.$eval(attrs.pickATime));
        },
        scope: {
            timeOptions: '=options'
        },
        templateUrl: '../Templates/timeoptions.html'
    };
});

Directive Template:

Min: {{timeOptions.startTime}} Max: {{customerInfo.endTime}}

HTML:

<input type="text" placeholder="Start Time" id="timestart" pick-a-time options="timeRange" data-ng-model="itemtimestart" class="form-control" autocomplete="off">

Controller to pass in dynamic values (stored in REST)

// Query settings for variables to be used later in function
appSettings.query(function(settings) {
    // Data is within an object of "value", so this pushes the server side array into a variable
    var setting = settings.value;

    // Foreach result, where setting is equal to active get the apporpriate variables
    angular.forEach(setting, function(settingvalue, settingkey) {
        if (settingvalue.Title == 'Active') {

            // Get work and non work durations as variables
            workDuration = settingvalue.Work_x0020_Day_x0020_Hours_x0020;
            nonWorkDuration = settingvalue.Non_x0020_Work_x0020_Day_x0020_H;

            // Get $scope variables to control time picker range
            var startHour = settingvalue.Work_x0020_Day_x0020_Start_x0020.split(":")[0];
            var startMinute = settingvalue.Work_x0020_Day_x0020_Start_x0020.split(":")[1];
            var startTime = '[' + startHour + ',' + startMinute + ']';
            var endHour = settingvalue.Work_x0020_Day_x0020_End_x0020_M.split(":")[0];
            var endMinute = settingvalue.Work_x0020_Day_x0020_End_x0020_M.split(":")[1];    
            var endTime = '[' + endHour + ',' + endMinute + ']';
            $scope.timeRange = {min: startTime, max: endTime};                  
        }
    })
});

The non-dynamic method (which works) on an input is as follows:

<input type="text" placeholder="End Time" id="timeend" pick-a-time="{min: [0,0], max: [23,30]}" data-ng-model="itemtimeend"class="form-control" autocomplete="off">

Update: Working with Dave, I have adjusted to the following. It logs the timeRange correctly, but gives an undefined for the timeOptions in the directive

timeRange Log:

 time start is [8,30]time end is [17,0]

timeOption log:

 time options log undefined

Directive (timeOptions undefined on logging):

appDirectives.directive('pickATime', function() {
return {
    // Restrict it to be an attribute in this case
    restrict: 'A',
    // responsible for registering DOM listeners as well as updating the DOM
    link: function(scope, element, attrs) {
        element.pickatime(scope.pickATime);
        console.log("time options log" + scope.timeOptions);
    },
    scope: {
        timeOptions: '='

    },
    templateUrl: '../Templates/timeoptions.html'
};

});

Template:

min: {{timeOptions.min}}, max: {{timeOptions.max}}

Controller (logs out correctly):

// Get $scope variables to control time picker range
var startHour = settingvalue.Work_x0020_Day_x0020_Start_x0020.split(":")[0];
var startMinute = settingvalue.Work_x0020_Day_x0020_Start_x0020.split(":")[1];
var startTime = '[' + startHour + ',' + startMinute + ']';
var endHour = settingvalue.Work_x0020_Day_x0020_End_x0020_M.split(":")[0];
var endMinute = settingvalue.Work_x0020_Day_x0020_End_x0020_M.split(":")[1];
var endTime = '[' + endHour + ',' + endMinute + ']';
$scope.timeRange = {
    min: startTime,
    max: endTime
};

HTML:

<input type="text" placeholder="Start Time" id="timestart" pick-a-time timeOptions="timeRange" data-ng-model="itemtimestart" class="form-control" autocomplete="off">

Update - Picker Working... but Now Form is not Submitting Time Data per this Post: TimePicker directive won't submit time (undefined)**

Huge thanks to @dave-alperovich and @joe-enzminger for tireless help and great answers.

Controller:

// Get $scope variables to control time picker range
var startHour = settingvalue.Work_x0020_Day_x0020_Start_x0020.split(":")[0];
var startMinute = settingvalue.Work_x0020_Day_x0020_Start_x0020.split(":")[1];
var endHour = settingvalue.Work_x0020_Day_x0020_End_x0020_M.split(":")[0];
var endMinute = settingvalue.Work_x0020_Day_x0020_End_x0020_M.split(":")[1];
$scope.timeRange = {
min: [startHour,startMinute],
max: [endHour,endMinute]
};

Directive:

appDirectives.directive('pickATime', function() {
return {
    // Restrict it to be an attribute in this case
    restrict: 'A',
    // responsible for registering DOM listeners as well as updating the DOM
    link: function(scope, element, attrs) {
        element.pickatime(scope.options());
    },
    scope: {
        options: '&pickATime'
    },
};
});

Usage:

<input ng-if="timeRange" type="text" placeholder="Start Time" id="timestart" pick-a-time="timeRange" data-ng-model="itemtimestart" class="form-control" autocomplete="off">

解决方案

There are many different ways to pass data from a parent scope into a directive. You've chosen (correctly) the class of choices offered by isolated scopes, as indicated by the

scope: {
}

parameter of your directive. This means that the scope of your directive will not prototypically inherit from the parent scope.

The reason your first example doesn't work is that the line:

element.pickatime(scope.$eval(attrs.pickATime));

ends up passing undefined to the element.pickatime() method.

This is because what this line of code does is attempt to evaluate the expression (which is a string) contained in the value of the pick-a-time html attribute from your DOM against the directive's scope. The value of the pick-a-time attribute is an empty string in your first example.

When you use the "non dynamic" version, the value of the pick-a-time attribute is now the string

"{min: [0,0], max: [23,30]}"

Which is a valid angular expression and $eval will return an object with min and max properties set to [0,0] and [23,30] respectively, so your directive works.

In both cases, your directive completely ignores the value passed in to the directive with the options attribute.

An easy fix would be to modify your directive to use the information passed in via the options attribute. The way your directive is written, this object will be two-way bound to the $scope.timeOptions value (more on this later). Essentially, any changes to $scope.timeOptions will show up in the parent scope's timeRange property, and vice versa.

The change to your directive would be to use:

element.pickatime(scope.timeOptions);

Extra credit:

In your last example, you state that timeOptions is undefined in the directive. This is because the html needs to be:

<input type="text" placeholder="Start Time" id="timestart" pick-a-time time-options="timeRange" data-ng-model="itemtimestart" class="form-control" autocomplete="off">

The only change is timeOptions -> time-options

This is how angular handles attribute to scope property mapping by convention.

Extra Extra Credit:

Your example does not require two-way binding (I don't think you want to change the options inside the directive). You can avoid the creation of two $watches by using & instead of =. This would be my final version of your directive:

appDirectives.directive('pickATime', function() {
    return {
        // Restrict it to be an attribute in this case
        restrict: 'A',
        // responsible for registering DOM listeners as well as updating the DOM
        link: function(scope, element, attrs) {
            element.pickatime(scope.options());
        },
        scope: {
            options: '&pickATime'
        },
        templateUrl: '../Templates/timeoptions.html'
    };
});

with usage:

UPDATE for dot notation issue:

In your controller, you need to use dot notation for itemtimestart:

.controller('xxx', function($scope){
    $scope.parameters = {
    }
}

<input ng-if="timeRange" type="text" placeholder="Start Time" id="timestart" pick-a-time="timeRange" data-ng-model="parameters.itemtimestart" class="form-control" autocomplete="off">

$scope.paramters.itemtimestart should now be the correct time.

You can also simplify this by using the "controller as" syntax.

Here is a Plunk

这篇关于为AngularJS指令动态选项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆