Four Methods Explained: What Works and What Doesn't
I recently created an angular js directive where I encountered difficulty accessing the ctrl.$modelValue
in the main flow.
In my quest to find a solution, I came up with four potential methods, each with its own set of advantages and drawbacks.
Method 1 didn't meet my expectations as it failed to provide the desired result. I couldn't find any other directly accessible property within the directive.
Method 2, on the other hand, worked by waiting for the current flow to finish before executing. This delay coincides with the completion of the angular js lifecycle, ensuring that the controller is linked to the model. However, I'm not entirely satisfied with this approach since it waits for all executions to complete before running the code.
Method 3 proved effective in accessing the model through $scope
and extracting the value from the string representation obtained from the attrs
object. The downside here is the use of eval to retrieve the targeted value, which is generally considered bad practice.
Method 4 does work, but it involves complex string manipulation and a while loop, making it seem convoluted for such a simple task. I doubt its robustness and wish for a simpler alternative, possibly implementing a for loop instead.
Given these options, I am unsure about the ideal method to choose. Perhaps there is a fifth method devoid of any drawbacks?
DEMO: http://jsfiddle.net/billymoon/VE9dX/9/
HTML:
<div ng-app="myApp">
<div ng-controller="inControl">
I like to drink {{drink.type}}<br>
<input my-dir ng-model="drink.type"></input>
</div>
</div>
Javascript:
var app = angular.module('myApp', []);
app.controller('inControl', function($scope) {
$scope.drink = {type:'water'};
});
app.directive('myDir', function(){
return {
restrict: 'A',
require: 'ngModel',
link: function($scope, element, attrs, ctrl) {
// Method 1
// logs NaN
console.log({"method-1": ctrl.$modelValue});
// Method 2
// on next tick it is ok
setTimeout(function(){
console.log({"method-2": ctrl.$modelValue});
},0);
// Method 3
// using eval to access model on scope is ok
// eval is necessary in case model is chained
// like `drink.type`
console.log({"method-3": eval("$scope."+attrs.ngModel)});
// Method 4
// using complex loop to access model on scope
// which does same thing as eval method, without eval
var getProperty = function(obj, prop) {
var parts = prop.split('.'),
last = parts.pop(),
l = parts.length,
i = 1,
current = parts[0];
while((obj = obj[current]) && i < l) {
current = parts[i];
i++;
}
if(obj) {
return obj[last];
}
}
console.log({"method-4": getProperty($scope,attrs.ngModel)});
}
};
});