I have a directive and I'm trying to pass Date/moment object via attribute. I'm passing it like this: (I know, that I can create isolated-scope and bind it, it is not the case)
<form name="form">
<input name="field" ng-model="fieldModel" form-field-directive field-date="{{fieldDateModel}}" />
</form>
Without curly brackets the result is obvious, but with I'm getting such quoted string "2015-07-03T10:35:13.691Z".
Is there anyway to work with it?
UPDATE:
angular.module('app', [])
.controller('AppCtrl', function($scope) {
$scope.fieldDateModel = moment(); // new Date()
});
angular.module('app')
.directive('formFieldDirective', function() {
return {
restrict: 'A',
require: '^ngModel',
link: function(scope, iElement, iAttrs, ngModelCtrl) {
ngModelCtrl.$validators.fieldDate = function() {
if (angular.isUndefined(iAttrs.fieldDate)) {
return true;
}
console.log(iAttrs.fieldDate);
};
}
};
});
You can actually pull the value from the parent scope using $parse which is more reliable.
angular.module('app')
.directive('formFieldDirective', function($parse) {
return {
restrict: 'A',
require: '^ngModel',
link: function(scope, iElement, iAttrs, ngModelCtrl) {
ngModelCtrl.$validators.fieldDate = function() {
if (angular.isUndefined(iAttrs.fieldDate)) {
return true;
}
console.log(($parse(iAttrs.fieldDate)(scope)).format());
};
}
};
});
http://jsbin.com/qoheraloge/1/edit?js,console,output
Related
I'm trying to get the value from one of the input fields in my form, but my code isn't working:
JavaScript:
angular
.module('myDirectives')
.directive('pwMatch', matchPassword);
function matchPassword() {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModelCtrl) {
var modelIt = attrs.pwMatch;
var inputValue = attrs.modelIt;
console.log(inputValue);
}
};
};
HTML:
<input name="telephone" type="number" value="223344455">
<div pw-match="form.telephone"></div>
If you are trying to get the value of an input, use ng-model.
<input ng-model="form.telephone" type="number" value="223344455">
<div pw-match input-name="form.telephone"></div>
And if you want to get that value in a directive using a name on an attribute, use the$watch method on the scope.
JS
angular.module('myDirectives',[])
.directive('pwMatch', function() {
return {
restrict: 'A',
link: function (scope, element, attrs) {
scope.$watch(attrs.inputName, function(value) (
var inputValue = value;
console.log(inputValue);
};
}
}
});
.module('myDirectives')
needs to be
.module('myDirectives', [])
Even though you have no dependencies, you have to have the empty array.
Also, it's a really bad idea™ to use a variable function as a directive or something, it's just going to confuse you.
This works, too, and might make your application a bit easier to maintain:
angular.module('myDirectives', [])
.directive('pwMatch', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModelCtrl) {
var modelIt = attrs.pwMatch;
var inputValue = attrs.modelIt;
console.log(inputValue);
}
}
});
I am creating an angular directive and I want the user to specify a 'type' of the directive.
For example:
<my-directive type-a></my-directive>
or
<my-directive type-b></my-directive>
or
<my-directive type-c></my-directive>
I know I can do:
<my-directive type="a"></my-directive>
and then require the type attribute but then I'm doing string matching. Is there anyway to do this by requiring one of 'type-a', 'type-b', or 'type-c' to be present?
Without much background info, I came up with this solution.
JSFIDDLE
So basically myDirective has a controller which is shared by type directives (type-a, type-b.. and so on). The type directive sets the type on the scope of myDirective.
myApp.directive('myDirective', function() {
return {
restrict: 'E',
controller: function($scope) {
$scope.type = '';
this.setType = function(type){
if($scope.type === '') $scope.type = type;
else throw 'type can be only defined once. Current type is '+$scope.type
}
},
link: function(scope, elem, attrs) {
console.log(scope.type);
}
}
});
myApp.directive('typeA', function() {
return {
restrict: 'A',
require: '^myDirective',
link: function(scope, elem, attrs, ctrl) {
ctrl.setType('typeA');
}
}
});
myApp.directive('typeB', function() {
return {
restrict: 'A',
require: '^myDirective',
link: function(scope, elem, attrs, ctrl) {
ctrl.setType('typeB');
}
}
});
I think you can do <div data-my-directive="a"></div> which is a lot safer for cross-browser and w3c. Then the directive would be something like:
.directive('myDirective', function() {
return {
restrict: 'A',
scope: {
type: '='
},
link: function(scope,element,attrs){
}
};
});
I have attempted the following which seems to generate the correct html, but doesn't perform the data binding i.e. the new directives that I add do not have access to the $modelValue in ngController:
.controller('MyController', ['$scope', function($scope) {
$scope.aModel = {"key": "value"}
function init() {
$scope.aModel = {"key": "value"}
}
}])
.directive('innerDirective', [function (){
return {
restrict: 'AE',
require: 'ngModel',
template: '<ul></ul>',
link: function(scope, elem, attr, ngModelController) {
console.log(ngModelController.$modelValue) // Doesnt work
}
}
}])
.directive('outerDirective', ["$log", "$compile", function($log, $compile) {
return {
restrict: 'AE',
require: 'ngModel',
scope: {},
template: '<div></div>',
link: function(scope, elem, attrs, ngModelController) {
ngModelController.$render = function() {
var aModel = ngModelController.$modelValue; // Works
var modelName = attrs['ngModel']; // aModel
var html = '<inner-directive ng-model="' + modelName + '"></inner-directive>';
var angularElement = angular.element(html);
elem.append(angularElement);
$compile(angularElement)(scope);
}
}
};
}])
HTML looks like:
<div ng-controller="MyController">
<outer-directive ng-model="aModel"></outer-directive>
</div>
This is based on reccomendations from another question: Adding ngModel to input with a directive
What is it that I'm doing wrong here?
Cheers.
There is two issue:
1- outerDirective is using isolated scope. so aModel value is undefinded in the directive scope.
2-You can't access ngModelController.$modelValue in link function immediately. Look at outerDirective that you access it in the render function.
So you can change your directives as follows:
var app = angular.module('app', []);
app.controller('MyController', ['$scope', function ($scope) {
$scope.aModel = { "key": "value" }
function init() {
$scope.aModel = { "key": "value" }
}
}]);
app.directive('innerDirective', ['$timeout', function ($timeout) {
return {
restrict: 'AE',
require: 'ngModel',
template: '<ul></ul>',
link: function (scope, elem, attr, ngModelController) {
$timeout(function () {
console.log(ngModelController.$modelValue) // It works
});
}
}
}]);
app.directive('outerDirective', ["$log", "$compile", function ($log, $compile) {
return {
restrict: 'AE',
require: 'ngModel',
template: '<div></div>',
link: function (scope, elem, attrs, ngModelController) {
ngModelController.$render = function () {
var aModel = ngModelController.$modelValue; // Works
var modelName = attrs['ngModel']; // aModel
var html = '<inner-directive ng-model="' + modelName + '"></inner-directive>';
var angularElement = angular.element(html);
elem.append(angularElement);
$compile(angularElement)(scope);
}
}
};
}]);
I am using ng-repeat and setting a model with it similar to the following
<div ng-repeat="thing in things" ng-model="thing" my-directive>
{{thing.name}}
</div>
then in my directive it looks something like this
.directive("myDirective, function () {
return {
require: 'ngModel',
link: function(scope, lElement, attrs, model) {
console.log(model.name);// this gives me 'NAN'
}
}
})
My question is how can I access the values in the model? I tried model.$modelValue.name but that did not work.
If you want to bind in a scoped value then you can use the '=' in an isolated. This will appear on the scope of your directive. To read the ng-model directive, you can use =ngModel:
.directive("myDirective", function () {
return {
scope: {
model: '=ngModel'
}
link: function(scope) {
console.log(scope.model.name); // will log "thing"
}
}
});
.directive("myDirective", function () {
return {
require: 'ngModel',
link: function(scope, lElement, attrs, model) {
console.log(attrs.ngModel); // will log "thing"
}
}
})
If your directive does not have isolated or child scope then you can do this:
.directive('someDirective', function() {
return {
require: ['^ngModel'],
link: function(scope, element, attrs, ctrls) {
var ngModelCtrl = ctrls[0];
var someVal;
// you have to implement $render method before you can get $viewValue
ngModelCtrl.$render = function() {
someVal = ngModelCtrl.$viewValue;
};
// and to change ngModel use $setViewValue
// if doing it in event handler then scope needs to be applied
element.on('click', function() {
var val = 'something';
scope.$apply(function() {
ngModelCtrl.$setViewValue(val);
});
});
}
}
});
Not sure how to phrase the question so please edit if you can come up with something better. I have the following directive:
app.directive('foo', function() {
return {
restrict: 'A',
require: "?ngModel",
link: function (scope, element, attrs, controller) {
scope.$watch(attrs.ngModel, function () {
console.log("Changed to " + scope[attrs.ngModel]);
});
}
};
});
When I have this it works great and logs properly
<input type="text" ng-model="bar" />
app.controller('fooController', function($scope) {
$scope.bar = 'ice cream';
});
It doesn't work when I try it this way around. It keeps logging 'Changed to undefined'
<input type="text" ng-model="model.bar" />
app.controller('fooController', function($scope) {
$scope.model = { bar: 'ice cream' };
});
How do I make it work for both scenarios. It seems the right thing to do seeing as angular lets you use both.
I looked at ngModel directive and found a function called ngModelGet. Uses $parse.
app.directive('foo', function($parse) {
return {
restrict: 'A',
require: "?ngModel",
link: function (scope, element, attrs, controller) {
var ngModelGet = $parse(attrs.ngModel);
scope.$watch(attrs.ngModel, function () {
console.log("Changed to " + ngModelGet(scope));
});
}
};
});
your can use
var ngModelCtrl = controller;
ngModelCtrl.$viewValue
replace
scope[attrs.ngModel]
here is ngModelCtrl sdk