Creating Duration Inputs (mm: ss: ms) in an AngularJS directive
source link: https://www.codesd.com/item/creating-duration-inputs-mm-ss-ms-in-an-angularjs-directive.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Creating Duration Inputs (mm: ss: ms) in an AngularJS directive
I have a form where I need users to input a time duration, in the resource this is saved as minutes (or milliseconds, easy change). I need the directive to take the second/millisecond value then create 3 separate inputs for the minutes, seconds & milliseconds.
Users can then modify each of the components and the directive will then update the model with the seconds/millisecond value of the 3 components.
I seem to be able to take the model value, create the 3 inputs and using moment.js create the separate components of time.
Directive
angular.module('myExampleApp')
.directive('lapTimeInput', function () {
var tpl = '<div class="lap_time_input"> \
<input ng-model="lap_time.minutes" type="number" class="minutes" placeholder="00" min="0" max="15" step="1"> \
<span class="lap-time-sep">:</span> \
<input ng-model="lap_time.seconds" type="number" class="seconds" placeholder="00" min="0" max="59" step="1"> \
<span class="lap-time-sep">.</span> \
<input ng-model="lap_time.milliseconds" type="number" class="milliseconds" placeholder="000" min="0" max="999" step="1"> \
</div>';
return {
restrict: 'A',
template: tpl,
replace: true,
require: 'ngModel',
scope: {
},
link: function (scope, element, attrs, ngModel) {
if (!ngModel) return;
scope.$watch(function () {
return ngModel.$modelValue;
}, function(newValue) {
// Using moment.js to extract min, sec & ms parts
var duration = moment.duration(newValue, 'seconds');
scope.lap_time = {
minutes: duration.minutes(),
seconds: duration.seconds(),
milliseconds: duration.milliseconds()
}
});
}
};
});
Controller
$scope.lap = Lap.get({ id: 1 }); // $resource contains .lap_time property
// OR
$scope.lap = {
lap_time: 90.999
}
HTML
<input type="text" lap-time-input ng-model="lap.lap_time" />
This Plunker will hopefully be a bit clearer
http://plnkr.co/edit/xmNtlItembSUFFZzaT9n?p=preview
Now I'm not even sure I've gone down the right path with using $watch on ngModel, I would guess not. As I understand it I need the directive to do 3 things:
- Replace the element with 3 separate inputs for minutes, seconds and milliseconds
- Show the model value to the user in the created inputs using the created inputs
- When the user changes any of the 3 inputs, it updates the model value turning the 3 separate values back into seconds/milliseconds
Even just a nudge in the right direction would be a great help
This is what I managed to come up with. Not exact answer but should help you on your way.
Template
Updated the template and passed in the lap time as an attribute to be retrieved via the directive scope (see directive section)
<div lap-time-input="lap.lap_time"></div>
Controller
angular.module('myExampleApp')
.controller('myExampleCtrl', function ($scope) {
// This would usually be a $resouce return via a serice
$scope.lap = {
lap_time: 90.999
};
// watch value of lap time change here when you update minute/second/millisecond
$scope.$watch('lap.lap_time', function (newLapTime) {
console.log('newLapTime', newLapTime);
});
});
Directive
Added the second/milliseconds input field to the template. You probably don't need it, but I put it there for visual/debug reason.
angular.module('myExampleApp')
.directive('lapTimeInput', function () {
var tpl = '<div class="lap_time_input"> \
<input ng-model="lapTimeInput" type="number" placeholder="00.00"> \
<input ng-model="lap_time.minutes" type="number" class="minutes" placeholder="00" min="0" max="15" step="1"> \
<span class="lap-time-sep">:</span> \
<input ng-model="lap_time.seconds" type="number" class="seconds" placeholder="00" min="0" max="59" step="1"> \
<span class="lap-time-sep">.</span> \
<input ng-model="lap_time.milliseconds" type="number" class="milliseconds" placeholder="000" min="0" max="999" step="1"> \
</div>';
return {
restrict: 'A',
template: tpl,
replace: true,
scope: {
lapTimeInput: '='
},
link: function (scope) {
// watch for changes in lapTimeInput and update the lap_time model/object
scope.$watch('lapTimeInput', function (newValue) {
var duration = moment.duration(newValue, 'seconds');
scope.lap_time = {
minutes: duration.minutes(),
seconds: duration.seconds(),
milliseconds: duration.milliseconds()
}
});
// watch for changes in the lap_time model/object
scope.$watchCollection('lap_time', function (newTime, oldTime) {
console.log(newTime);
// convert back to lap time with momentjs here
scope.lapTimeInput = moment.duration(newTime, 'seconds').asSeconds();
});
}
};
});
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK