2015-04-02 68 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