AngularJs dynamic form generation with validation - angularjs

I am trying to generate form dynamically and use validation at the same time. The problem that I have now is that the input attribute name='{{key}}' is not interpolated by the validation.
<div ng-repeat="options in formObject">
<input type='radio' ng-model='ranodm' name='{{key}}'>
</div>
I know that I should use ng-form if I want a dynamic form, however I am having hard time to understand it. I am adding my simple plnkr example of what I am trying to achieve. It would be nice if someone would show how to solve this using ng-form or other method.
http://plnkr.co/edit/faG89bmu18nNNODVRV3x

I found an answer from reading through this SO post: Dynamic validation and name in a form with AngularJS
I ended up using the dynamicName directive to work around this problem so I could use a UUID of as the name of the field. Here's a plnkr and the directive I used. I can't take credit for the directive, I found it on that other post.
http://plnkr.co/edit/RFrRXp2kWkP1Mefwl3Kn?p=info
myApp.directive('dynamicName', function($compile, $parse) {
return {
restrict: 'A',
terminal: true,
priority: 100000,
link: function(scope, elem) {
var name = $parse(elem.attr('dynamic-name'))(scope);
elem.removeAttr('dynamic-name');
elem.attr('name', name);
$compile(elem)(scope);
}
};
});

Go through following link this will help.
http://www.benlesh.com/2013/03/angular-js-validating-form-elements-in.html

Related

How to not refer to the controllerAs name in directive

Here is the minimal code to describe the issue. On the page, I have:
<div ng-controller='AController as a'>
<div a-directive></div>
</div>
In js, I have:
app.directive("aDirective", function($compile){
return {
scope: true,
link: function(scope, element, attrs) {
var template = "<h1>{{a.label}}</h1>";
element.append($compile(template)(scope));
}
}
});
app.controller("AController", function($scope){
self = this;
self.label = "some text";
});
That works, but the issue is that {{a.label}}, which made the view and controller/model tightly coupled. Is there any way to get rid of that a., and not to mention the controllerAs-name in the directive code at all? (just like what I did in the controller code)
To improve this you can pass the text to display as a parameter to the directive. Something like this is the initial idea:
<div a-directive="a.label"></div>
However, I DO recommend using an alias for the controller, so I made a Plunker where you can see all of this working together with some improvements.
Check it out here: http://plnkr.co/edit/1hBSBxwSEPXoj9TULzRQ?p=preview
I would also recommend to use template instead of link and restricting the directive to an element instead of using it as attribute, since it is modifying the DOM. But yeah, you could keep improving it till the end of the times :)

Angular-strap datepicker doesn't update existing model value

I am using angular-strap datepicker from http://mgcrea.github.io/angular-strap/##datepickers for my angularjs SPA project. when editing an existing record using ngModel two way binding, Angular doesn't detect the date field change and even if I force the form to save by updating another non date field, the new date is not updated in backend. Here is the related part in my html file:
<input name="DecisionDatePicker" id="ddpID" type="text" class="form-control input-medium" tabindex="14" placeholder="{{vm.format}}"
data-date-format="MM-dd-yyyy"
data-ng-model="vm.formData.dateDecision"
data-ng-required="vm.decisionDateRequired"
bs-datepicker />
I do not do anything special in my js file. I am using breezejs for my data handling and it is working fine for other fields.
what am I doing wrong? Any help is appreciated.
I've had this same problem and I solved with a custom directive that updates the model when the bs-datepicker dispatches a blur event:
angular.module('moduleName').directive('updateModelOnBlur',
['$parse', function($parse) {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, elm, attrs) {
elm.bind("blur", function (event) {
scope.$apply(function () {
var model = $parse(attrs.ngModel);
model.assign( scope, elm.context.value );
});
});
}
};
}]
);
I know this is just a hack, and not a final solution for the problem. But, if you are stuck and want to keep going, sometimes a hack might be useful.
You can also include $filter service in the directive if you want to manipulate date format before updating model. ;)

AngularJS datepicker ui-date bad updates

The two-way data-binding appears to be causing bad updates to the field. Clicking on the field raises the datepicker fine, but if you attempt to edit the field by directly typing in a date, it doesn't quite work.
Here's the fiddle demonstrating the issue: http://jsfiddle.net/vSNJF/
<input type="text" ng-model="name" ui-date-format='m/d/yy' ui-date>
Compare the keyboard-editing under Angular to the standard jquery UI date picker behavior here: http://jqueryui.com/datepicker/
How can I make ui-date delay updating the model until after the interactive calendar is dismissed?
You've got quite a big directive there, I am not sure if anyone is going to go through the whole code to find what is causing the problem. To help I will leave a simpler datepicker directive that behaves exactly like Jquery UI's but without all the features you have implemented in yours, maybe if your start from this point and go adding features it would be easier to debug the problem.
The directive is:
directive('datepicker', function() {
return {
restrict: 'A',
require : 'ngModel',
link : function (scope, element, attrs, ngModelCtrl) {
$(function(){
element.datepicker({
dateFormat:'dd/mm/yy',
onSelect:function (date) {
ngModelCtrl.$setViewValue(date);
scope.$apply();
}
});
});
}
}
});
Here is a Plunker and a blog post about it.

Angular (directive newbie): How to add date time-picker to ngModel so that it can be validated?

I am very new to Angular and have a specific use case in mind
I have a form which has two fields - Name and datetime.
The name is ng-model but datetime is not since it is not part of Angular and is a jquery component
What I want to do?
Here is the plunker = http://plnkr.co/edit/wGrvXAFmPGoYSwh9GfxH?p=preview
a.) I want to associate date to ngModel like ngModel="transaction.date"
b.) validate it as required using Angular way
Something which will look like (much like Angular)
<input type="text" name="transactionDate" ng-model="transaction.date" data-date-format="yyyy-mm-dd hh:ii" required>
Why?
a.) To to things Angular way
b.) It makes model more consistent to test, validate
I asked this question on Stackoverflow and it was recommended to use custom directive, can someone give me direction with example how to do it?
Please guide me further since I am not able to validate it currently
Thank you very much
Based on Ketan's answer, I had to write a new directive and associate the value form jQuery to ng-model, which then is validated with form. The directive looks like
app.directive('dateTime', function(){
return {
restrict: 'A',
require: '?ngModel',
link: function(scope, element, attrs, ngModel){
if (!ngModel) {
console.log('no model, returning');
return;
}
element.bind('blur keyup change', function() {
console.log('datetime changed: ', $('.form_datetime input').val());
scope.$apply(read);
});
read();
function read() {
ngModel.$setViewValue(element.val());
}
}
}
});
The plunker can be found here
Assuming you know how to write directives, you need to use the NgModelController inside your directive and use the $setViewValue(value) method. (See example the below page).
http://docs.angularjs.org/api/ng.directive:ngModel.NgModelController
This has to be called from your custom Datepicker event which triggers when the user completes the selection.

how to pass a json as a string param to a directive

When I try to eval the below json form it gives me an error -
eval("{form: 'form' , nameToMatch: 'password1'}")
Why is the above form not valid ?
However the below works fine -
eval("{form: 'form'}")
I am trying to pass the above json as a string, as a param input to a directive.
Below is the html -
<input type="password" name="password2" ng-model="user.confirmPassword" placeholder="Confirm Password" match="{form: 'form', nameToMatch: 'password1'}" required="required"/>
Thanks,
Murtaza
Put parens around your json:
eval("({form: 'form' , nameToMatch: 'password1'})")
Doesn't seem like an angular question though. Not sure what you're trying to do:
Anyhow, to pass the json to the directive there are lots of ways to do that. I'm not sure why you'd want to do that and not just pass an object though.
passing json can be done a lot of ways...
From your attributes object:
app.directive('foo', function () {
return function(scope, element, attrs) {
var obj = eval('(' + attrs.foo + ')');
};
});
where
<div foo="{'test':'wee'}"></div>
From an isolated scope:
app.directive('foo', function () {
return {
restrict: 'E',
scope: {
'jsonIn' : '#'
},
link: function(scope, element, attrs) {
var obj = eval('(' + scope.jsonIn + ')');
};
};
});
where
<foo json-in="{'test':'wee'}"></foo>
But it's by far better to avoid using the native eval at all costs, if you can. Which in almost all cases you can. If you have some data just put it in an object on a scoped parameter and pass it in either via a two-way property on an isolated scope, or by name and do an angular $eval on it.
EDIT: The pass an object in...
You could use two way binding on an isolated scope:
app.directive('foo', function (){
return {
restrict: 'E',
scope: {
'data' : '='
},
link: function(scope, elem, attrs) {
console.log(scope.data);
}
};
});
where
<foo data="{ test: 'wee' }"></foo>
The really cool thing about doing it this way, is if you're using a scoped property it will update bi-directionally:
app.controller('MainCtrl', function($scope) {
$scope.bar = { id: 123, name: 'Bob' };
});
where
<foo data="bar"></foo>
I hope that helps.
It looks like you are trying to confirm a password in a form. There are many ways that you can go about this without resorting to JSON to pass values around in AngularJS. The most useful resource I've found online is from this Google Group thread:
1) http://jsfiddle.net/pkozlowski_opensource/GcxuT/23/ will compare
value in a second field with model value of the first field
2)
http://jsfiddle.net/S8TYF/ will compare value in a second field with
input value of the first field
The difference might be subtle but has practical consequences: with
(2) the confirm validation will kick-in as soon as you start typing
anything in the first field. With (1) the confirm validation will
kick-in only after the first field is valid. In the e-mail confirm
example it means that you won't start showing confirmation errors till
e-mail validation errors are sorted out (so a user can focus on one
error at the time).
Source: https://groups.google.com/d/msg/angular/R4QeNsNksdY/migbplv8GxIJ
From the first link, the directive is used as follows:
<label>e-mail</label>
<input name="email" type="email" required ng-model="email">
<label>repeat e-mail</label>
<input name="emailRepeat" type="email" required
ng-model="emailRepeat"
ui-validate-equals="email">
Where the ui-validate-equals directive points to the email model that was defined in the first input.
There are some StackOverflow answers to this if you would like to look there as well for additional ideas to solve your problem.
See also. #Blesh has mentioned in passing, but not emphasized: Angular provides you with a 'safe'-ish version of eval(), which works perfectly for passing declarative objects/arrays into your directive if you don't want to declare them on your scope, and wisely don't want to use native eval(). In the OP's example, just use this inside the directive:
angular.$eval(attrs.match);
Doesn't seem like an angular question though.
Agreed - vanilla JS can handle this just fine.
// Markup (HTML)
<div mydirective='{"test1": "foo", "test2": "bar"}'></div>
// App (JS)
JSON.parse(attrs['mydirective']);
Use JSON.parse(string) in angular. be sure that your parameter is in string format.

Resources