2015-04-02 54 views
2

我想将动态变量传递到显示时间选择器的指令(pickadate.js:http://amsul.ca/pickadate.js/time/)。但是,我正在努力如何让选项进入指令。我在互联网上搜索,但看到了很多方法,并且对于如何以最佳方式构建它而感到困惑,因为它不起作用。这是我的当前代码:AngularJS指令的动态选项

指令:

// 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' 
    }; 
}); 

指令模板:

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"> 

控制器以在动态传递值(存储在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};     
     } 
    }) 
}); 

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

<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"> 

更新:与戴维工作时,我已经调整到以下内容。它正确地记录了TIMERANGE,而是给出了一个未定义的timeOptions在指令

TIMERANGE登录:

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

timeOption日志:

time options log undefined 

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

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' 
}; 

}); 

模板:

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

控制器(注销正确):

// 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"> 

更新 - 选择器工作......但现在形式不提交按照该帖子时间数据TimePicker directive won't submit time (undefined) **

非常感谢@ dave-alperovich和@ joe-enzminger for tire较少的帮助和很好的答案。

控制器:

// 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] 
}; 

指令:

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' 
    }, 
}; 
}); 

用法:

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

回答

3

有许多不同的方法来从父传数据范围转化为指令。您已选择(正确)之类的采用隔离示波器提供的选择,你的指令的

scope: { 
} 

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

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

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

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

这是因为这行代码所做的是试图根据指令的作用域来评估DOM中pick-a-time html属性的值中包含的表达式(这是一个字符串)。 pick-a-time属性的值在第一个示例中是一个空字符串。

当您使用“非动态”版本中,取一个时间属性的值现在是字符串

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

这是一个有效的角度表达和$ EVAL会返回一个对象与分和max属性分别设置为[0,0]和[23,30],因此您的指令工作。

在这两种情况下,您的指令完全忽略了使用options属性传递给指令的值。

一个简单的解决方法是修改您的指令以使用通过options属性传递的信息。在写入指令的方式中,此对象将双向绑定到$ scope.timeOptions值(稍后会详细介绍)。实质上,对$ scope.timeOptions的任何更改都会显示在父作用域的timeRange属性中,反之亦然。

你的指令的变化是使用:

element.pickatime(scope.timeOptions); 

附加题:

在你的最后一个例子,你指出timeOptions在指令未定义。这是因为HTML必须是:

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

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

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

额外加分:

您的例子并不需要双向绑定(您想更改指令内的选项,我不认为)。您可以使用&而不是=来避免创建两个$手表。这将是我对你的指令的最终版本:

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' 
    }; 
}); 

与用法:

更新点符号问题:

在你的控制器,你需要使用点符号为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. 

您还可以通过使用“控制器as”语法来简化此操作。

Here is a Plunk

+0

'element.pickatime(scope.options())'我在想scope.options是一个对象而不是函数。 – Scottux 2015-04-16 13:19:48

+0

它在DOM中返回这个值,并且不会过滤时间。 aria-haspopup =“true”aria-readonly =“true”aria-readonly =“false” “false”aria-owns =“timestart_root”type =“text”readonly =“”placeholder =“开始时间”data-ng-model =“itemtimestart”autocomplete =“off”pick-a-time =“timeRange”> min :,max: – Kode 2015-04-16 13:34:44

+0

我的模板目前是:min:{{options.min}},max:{{options.max}}是否正确? – Kode 2015-04-16 13:38:20

0

如果选择已经存在(在timeRange)且不会随着时间而改变,你有无关:它应该在scope.timeOptions(都在你的链接和控制器中)。

但是,如果选项都可以随时更改,并要刷新composant当它,你需要注意它的变化:

scope.$watch('timeOptions', function(newOptions) { 
    // do something with the newOptions 
}); 
+0

所以我的代码应该工作?由于更新很少发生?在这一点上,时间选择器并没有反映变量 – Kode 2015-04-02 22:00:12

+0

你应该对选项做什么?如果你只需要在你的模板中显示它们,事实上这应该足够了。 – floribon 2015-04-02 22:08:41

+0

我需要将它们用作指令中的变量来控制时间范围。 – Kode 2015-04-02 22:46:27