I've got a json file that generates the form definitions for each specific form. In the view - I spit out the data something like this
<input ng-data-model="data[value2.Id]" placeholder="{{value2.Label}}" type="text" />
<button ng-click="send_form()" >Submit</button>
In my controller, I've got the following function
$scope.send_form = function() {
alert($scope.data);
}
When the send_form function is called - i get "undefined" returned back. My question is, how do i handle dynamic form data in Angular JS and get each of the values inserted by the user? Is there a way to get a key/value pair set of data returned? with the ng-data-model has the key and the value inserted by the user as a user? Or how would i handle this specific scenario? Any help would do :)
Thanks :)
It's just ng-model to bind your input to your scope variable. Or you can use data-ng-model for compliance. Other than that it should work if your data is set up - might help to show an example of how it looks.
Here's a fiddle with some dummy data:
https://jsfiddle.net/ba0pj6sv/
Related
I am creating a dynamic form from angular in index.html using ng-repeat over an array of JSON object. On submit button, I need to pass form data into a post request in form of a map like :
{"key":value,"key":value}
The key is dynamic label generated in the form and value is the input from a text field or drop-down. Please help me. How I can create a map dynamically? You can find my code here.
I solved my problem. This was a little bit tricky to create a map from dynamic form. Code has been updated on plunker.
Step:
I declared a json object response at script.js.
Response[filed.attributeLabel] will work as a key and value will be bind when we select or enter some thing in dropdown or text filed avvording to key in scope variable.
I am trying to create exactly same form given in this fiddle
steb by step angular form
but whenever i click on the next button data entered in the first step resets.. how can i prevent this? On submit all data is undefined while reading in javascript.
Please help me..
In the JsFiddle code you provided you are not retaining the users data, meaning that data is being Binded to anything in the controller. So when leave the section the data is removed.
To retain data make the following changes:
// In your controller add the following object to the $scope
$scope.user = {}
// In your HTML code add the following to your input fields
<input type="text" id="teamName" ng-model="user.teamName" placeholder="Team Name" />
Notice the ng-model tag in the input field this is what binds your data to the user object within your controller
Heres a working JsFiddle, please note that I only updated the Team Name field. Type something in the Team Name field and go to the next section and it will retain your data. You will need to update the remaining fields.
in the usual javascript form submit , what happens is that when i do the post the element names and values automatically are sent in the HTTP request to the server without me having to collect each one of them .
what I have noticed in angular form submits is that is not the case . based on ng-submit example I have to collect each ng-model i have in the view into my controller and I have to do that in the submit function I write .
My question
isnt there a way where I can collect everything from the view without having to refer to all of the ng-models in my controller ?
Why ?
there is this case where the form elements are dynamically drawn from a directive and its not very practical to refer to each when they are so many .
Any advice ?
It depends on app to app. If yours is a SPA then you have to make sure you use ng-submit and submit the form.
When you add dynamic elements to a form if you make sure you also add the ng-model accordingly then you dont have to worry about them. It will be part of the form submission.
I think what you can do is, all the form fields(even dynamic elements) can be maintained in an object e.g. formData and then add all the models into this object. Now in the submit method you can read all the form elements values (event the dynamic elements value) using formData object.
Whenever you add a dynamic element make sure it is added to formData object
E.g.
<input ng-model="formData.field1" type="text">
<input ng-model="formData.field" type="text">
Inside submit method you can get the form field vlaues using $.param($scope.formData)
I'm developing a friend invitation feature for a website.
Only requirements are : by email and has a max number of invitations at a time.
My idea is the following :
At the start, user only sees one email field. When he enters an email adress in the only field, angularjs validates it (email format check) and creates an additional email field.
Now, I come from a jquery background and I think it's bad practice to manipulate DOM with angular.
How would one do it with angularjs ?
Is it a good idea to create a factory that "produces" (from a template file) fields ?
Can a library like bootstrap ui help me write simpler code for form validation and error management
This Plunker might fulfill your need at its closest: http://plnkr.co/edit/5qRXQ1XGzUnhYjLCiyYR?p=preview
The key point in this technique is letting the user directly edit a dynamic list of models. Indeed in the example, $scope.invites contains your values. The trick here is referring to them as models:
<input type="email" class="invite" name="invite{{ $index }}" ng-model="invites[$index].mail" ng-change="checkInvite($index)" />
$index being the index of the current ng-repeat iteration. checkInvite function will take care of watching changes in your invites fields.
Notes:
invites is an array of objects, this way we're sure not to mess with ng-repeat, iterating over the reference that we handle (vs models that would be handled by angular)
The field's name is useful to manually check the field's validity: in the controller we can check a field's validity accessing $scope.formName.fieldName.$valid
I also added an extra test that checks if the user clears a non-last filled-in field. In this case, we remove the field.
Have fun using angular!
Personally, I would find the design confusing, since I wouldn't know I could have more email addresses. At the minimum, I would want a + to indicate to the user that s/he can add more addresses. Think of how airlines do "multiple destinations" searches on their Websites.
However, if you are set at this, use an array in the scope. I am using a table for this, but anything will do.
<input ng-model="newemailaddress"></input><button ng-click="addEmail">Add</button>
<table>
<tr ng-repeat="addr in addresses"><td>{{addr}}</td></tr>
</table>
And your controller something like:
.controller('MyCtrl',function($scope) {
$scope.addresses = [];;
$scope.newemailaddress = "";
$scope.addEmail = function() {
// do validation
if (valid) {
$scope.addresses.push($scope.newemailaddress);
$scope.newemailaddress = "";
};
};
})
I have implemented a remote validation directive which queries a specified JSON API endpoint once an input is blurred. It expects the response { valid: true|false }.
I now have to extend it to allow for it to send a request involving multiple values from the parent scope.
My tag definition looks as follows:
<input remote-validate endpoint="/api/action/:value" ng-model="MyInput" />
where :value is substituted with a urlencoded value of $scope.MyInput.
This is working well.
What I require is given an endpoint like this /api/action/:value/:person/:thing, the :person and :thing substitutions are bound to the parent scope values.
My initial thought is to have a bindings attribute which maps the parent scope to the endpoint.
<input remote-validate endpoint="/api/action/:value/:person/:thing" bindings="{person: 'firstName', thing: 'thingName'}" ng-model="MyInput" />
(...)
<input ng-model="firstName" /> <input ng-model="thingName" />
given var bindings = scope.$eval(attrs.bindings); is there any way to loop through the bindings object and create a two way binding to the parent scope?
EDIT: A workaround may be to do this:
<input validate-remotely
endpoint="api/action/:value/:param1/:param2"
param1="person"
param2="thing" />
which obviously means I can only use the number of parameters I specify in the scope definition. Which is a good work around for me here. Would be nice to know if there was a way to create these bindings dynamically at compile/link time.
I can provide a fiddle but I don't have the time right now, so I'm hoping that someone will have a good idea if/how this is possible.
As I learned yesterday, you can use $parse on your 'binding' attributes. See this post. This is a good way to $watch an attribute for changes that come from parent or children
Example:
<div parse-test bindings="{person: 'firstName', thing: 'thingName'}"></div>
// in your directive link function:
scope.bindings = $parse(attrs.bindings)(scope);
scope.$watch('bindings', function(val){
for (i in scope.bindings){
scope[i] = scope.bindings[i];
}
}, true);
Experiment with this plunk
This is how I solved it in a not so ideal way.
See this plunker, which has a copy of the directive I use live and works well in my app but doesn't work in Plunker (I expect the randomly chosen plunker api endpoint to be called and fail, but it is not called due to some strange errors I don't care to debug).
The problem I had with the proposed workaround in the EDIT of this question is that it seems you cannot use scope and require in the same directive. I would love it if someone could elaborate on if this is the case and why.
The Workaround
I used a params attribute to specify additional data in object notation to be extended to go to the resource request. I used the handlebars syntax in the params attribute to dynamically change the object notation string.
<input ng-model="value2" ... />
<input validate-remotely
endpoint="/api/:value/?thing=:anotherValue"
params="{ anotherValue: '{{ value2 }}' }" ... />
Not so great :/ but it works.
Then on blur of the validated input, I re-$eval the object string (app.js:40 in the plunker) and extend the resources data to include this object, which using ngResources colon (:) notation, replaces the URL.
The validation has 3 states:
remoteValidityPending: field validation fails because it is still being checked - good for showing a spinner.
remoteValidityUnchecked: The field has changed since it has been checked but has not yet blurred - ensures that any `ng-disable="form.$invalid"' submit buttons stay disabled until we know that the backend has returned a response.
remoteValidity: If this passes, the fields endpoint has been called and '{valid: true}' has been returned from the server.
I'm almost certain there are better/different ways to solve this, and I'll be happy to change the answer if someone improves this directive. I hope this helps someone out there.