post data inside clone div angularjs ng-model - angularjs

Clone div is repeating, when I click add button.
How can I post the fields inside clone div.
<div class="row" id="append-row">
<div class="clone-div-{{count}}" id="clone-div">
<div class="col-md-6">
<div class="form-group input-group-sm">
<label>Title</label>
<input type="text" class="form-control" id="addTitle" placeholder="Title" ng-model="chapters.chapter.title">
</div>
</div>
<div class="col-md-6">
<div class="form-group input-group-sm">
<label>Select Language</label>
<select class="form-control" name="country" id="country" ng-model="chapters.chapter.languageID" ng-options="value.ID as value.language for value in technical.languages">
<option value="">Select Country</option>
</select>
</div>
</div>
</div>
</div>
This part is angularjs code.
$scope.count = 1;
$scope.addChapter = function() {
var iEl = angular.element( document.querySelector('#append-row') );
var wEl = angular.element( document.querySelector('#clone-div') );
iEl.append(wEl.clone());
$scope.count+=1;
};

You should do cloning/repeating inside the template in a ng-repeat and have the data prepared beforehand, that is a much cleaner way. You'll notice for example in the template code you have, all the ng-model's are the same, and will always display the same information if you have 1 'clone' div or 100.
A better method would be to write your clone div in the template and use it as a repeatable ng-template 'script', for example:
// main template
<script type="text/ng-template" id="cloneable.html">
// Your code here, but change reference to ng-model, ie this line as an example:
<input type="text" class="form-control" id="addTitle" placeholder="Title" ng-model="chapters.chapter[$index].title">
</script>
// main template, your new repeat then includes the repeatable script
<div ng-repeat="foo in manyFoos"
ng-include="'cloneable.html'"></div>
This way you can use the $index that arises from ng-repeat, as part of the model to accurately separate each individual repeat block. In your controller, chapters.chapter will be an array of objects.
I don't know about the 'add' button part or what information you're adding, but the above should take care of the model problem you'll be encountering.

Related

form.$valid undefined in angularJS

When I used angular form validation, it gives undefined error in angular controller.
My HTML View
Index.xhtml (Main View)
<div>
<select ng-model="val">
<option value="A"></option>
<option value="B"></option>
<option value="C"></option>
</select>
<div ng-if="item.value=='A'">
#Html.Partial("A")
</div>
<div ng-if="item.value=='B'">
#Html.Partial("B")
</div>
<div ng-if="item.value=='C'">
#Html.Partial("A")
</div>
</div>
A.chtml (partial view)
<div>
<form name="formA" ng-submit="A();">
<div ng-model="model1" required>
</div>
<input type="submit" value="Add"/>
</form>
</div>
B.chtml (partial view)
<div>
<form name="formC" ng-submit="B();">
<div ng-model="model2" required>
</div>
<input type="submit" value="Add"/>
</form>
</div>
JS File
$scope.A = function(){
if($scope.formA.$valid){
}
};
First I Select Value A in main view drop-down and, insert data and clicked Add button. Then it will checked the form validation. if validation true, function work success.
But,
after that I select value C i drop-down and try add inserted value, angular controller cannot identify the form name. It gives undefined error.
If I select B value after A selected, function execute without error. I tried to after set
$scope.formA.$setPristine();
$scope.formA.$setUntouched();
But It doesn't give any effect for this erro.
Can anyone help me?
any explanation about internal functionality?
You must have $scope prefixed to formA, that was more than likely the issue

How to repeat duplicate objects using ng-repeat in AngularJs?

This is my code.
$scope.data=[];
$scope.data=[{"label":"name","type":"string"},{"label":"email","type":"string"}];
$scope.addFields = function (field) {
$scope.data.push(field);
};
This is my html:-
<div ng-repeat="eachItem in data">
<input type="button" value="add" ng-click="addFields(eachItem)"/>
<label>{{eachItem.label}}</label>
<input type="text" ng-model="fieldValue"/>
</div>
when i click add button push one more object into $scope.data array like
$scope.data=[{"label":"name","type":"string"},{"label":"email","type":"string"},{"label":"name","type":"string"}];
In the above i got an error
angular.min.js:102 Error: [ngRepeat:dupes] http://errors.angularjs.org/1.3.14/ngRepeat/dupes?p0=nestedField%20in%20fie…%2C%22type%22%3A%22string%22%2C%22%24%24hashKey%22%3A%22object%3A355%22%7D
at Error (native)
I have duplicate objects after adding. because i want to repeat label names using ng-repeat in angularjs.First i have output like this
OutPut:-
name textbox
email textbox
After add button click Output:-
name textbox
email textbox
name textbox
use track by $index
var app = angular.module("app",[])
app.controller('ctrl',['$scope', function($scope){
$scope.data=[];
$scope.data=[{"label":"name","type":"string"},{"label":"email","type":"string"}];
$scope.addFields = function (field) {
$scope.data.push(field);
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<div class="item item-checkbox">
<div ng-repeat="eachItem in data track by $index">
<input type="button" value="add" ng-click="addFields(eachItem)"/>
<label>{{eachItem.label}}</label>
<input type="text" />
</div>
</div>
Use track by for this purpose.
<div ng-repeat="eachItem in data track by $index">
<input type="button" value="add" ng-click="addFields(eachItem)"/>
<label>{{eachItem.label}}</label>
<input type="text" ng-model="eachItem.value" />
</div>
You also able to use track by with your custom filed, like id, or whatever
Important: It's better to use track by in each ng-repeat, cause it's improve ng-repeat's performance (read more).
But avoid to use track by in ng-options and other cases when you use select as .. for ... construction (read more)
JsFiddle here
You have to ensure that items in the array have an unique key. If that is not possible you can use track by $index in the ng-repeat.
Check the details here

Angular validator, pass data along with error code to be displayed in ngMessages

Is that possible to store some additional data along with the error flag itself, using standard Angular mechanism?
i.e. I'm manually setting ngModel.$setValidity, I'd like to pass some data along with the error flag, to be displayed in ngMessages directive.
For example let's assume the min/max length of the field depends upon some external factors, thus is computed & validated server-side. The server respons with customlength error code along with max and min properties, which I'd like to display to the user.
Currently I'm simply setting ngModel.$setValidity("customlength", false); but I'd like to pass {max: response.max, min: response.min} along, to be interpolated in the template like <div ng-message="customlength">the length should be between {{ data.min }} and {{ data.max }}
I'd like to pass {max: response.max, min: response.min} along, to be interpolated in the template like the length should be between {{ data.min }} and {{ data.max }}
Use the root scope to store the value(s) intended to be output within the message string:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular-messages.js"></script>
<script>
angular.module('ngMessagesExample',['ngMessages']);
</script>
<body ng-app="ngMessagesExample">
<form name="myForm" id="{{$root.$id}}">
<label>
<p>Enter Min:<input type="text" ng-model="form_min">
<p>Enter Max:<input type="text" ng-model="form_max">
<p>Enter your name:
<input type="text"
name="myName"
ng-model="name"
ng-minlength="form_min"
ng-maxlength="form_max"
required />
</label>
<p>
<input type="radio" required name="foo" ng-model="foo" value="1">Yes
<input type="radio" required name="foo" ng-model="foo" value="2">No
</p>
<p>
Foo: <input type="text" ng-model="myForm.foo.$modelValue">
</p>
<p>
<input type="submit" value="{{myForm.foo.$error.required ? 'No' : 'Yes'}}">
</p>
<pre>myForm.myName.$error = {{ myForm.myName.$error | json }}</pre>
<div ng-messages="myForm.foo.$error" style="color:maroon" role="alert">
<div ng-message="required">Pick one</div>
</div>
<div ng-messages="myForm.myName.$error" style="color:maroon" role="alert">
<div ng-message="required">Your value should be between {{form_min}} and {{form_max}} characters long</div>
<div ng-message="minlength" id="{{$id}}">Your value is less than {{form_min}}</div>
<div ng-message="maxlength" id="{{$id}}">Your value is greater than {{form_max}}</div>
</div>
</form>
</body>
References
Easy Form Validation in AngularJS with ngMessages — SitePoint
AngularJS: Developer Guide: Migrating from Previous Versions
Explicitly providing ng-model to DOM elements | TO THE NEW Blog
Using NgModelController with Custom Directives

AngularJS ng-options not populating

I have an array of objects that I bind to the scope. My view then accesses the objects via ng-options like this:
<div class="tile block box-shadow">
<form role="form">
<div class="form-group">
<label>Reason for change</label>
<select class="form-control" ng-options="item.value as item.description for item in controller.priceChangeReasons" />
</div>
</form>
</div>
but the dropdown has nothing when you select it.
I have logged the priceChangeReasons and can see that the array is working and returning values.
I have made a codepen to show the issue:
http://codepen.io/r3plica/pen/XbQzMa?editors=101
I realise this is probably a syntax error on my part, but I can't see it.
Can someone help?
ngOptions directive requires ngModel, just add:
<select class="form-control" ng-options="item.value as item.description for item in controller.priceChangeReasons" ng-model="controller.reason" />
and all should work

AngularJS - how to sync result of calculated input field to a scope variable

I'm trying to sync the result of a calculated form field into a scope variable. For example:
<div class="form-group">
<label for="val1" class="control-label">Val 1</label>
<input class="form-control" name="val1" type="number" ng-model="data.val1" id="val1">
</div>
<div class="form-group">
<label for="val2" class="control-label">Val 2</label>
<input class="form-control" name="val2" type="number" ng-model="data.val2" id="val2">
</div>
<div class="form-group">
<label for="score" class="control-label">Score</label>
<input class="form-control" name="score" value="{{data.val1+data.val2}}" type="text" id="score">
</div>
<br/>data: {{data}}
How can I sync the result (i.e. the score field) into the scope variable $scope.data.score? I have tried ng-model="data.score" but that breaks the calculation.
You can see the example in action here:
http://plnkr.co/edit/fc9XcyyYGtAk0aGVV35t?p=preview
How do I get the last line to read data: {"val1":1,"val2":2,"score":3}?
Note that I'm looking for a solution that involves minimal to no code support at the controller level. For example, I know you can set up a watch in the controller for both val1 and val2 and then update the score in the watcher. This is what I wanted to avoid, if it's possible in angular at all. If it's not (theoretically) possible, I'd really appreciate an explanation of why it's not.
A quick background might help. Basically we have a simple form builder app that defines a form and all its fields in an xml file. Here's a sample of what the xml would look like:
<form name="test">
<field name="val1" control="textbox" datatype="number">
<label>Val 1</label>
</field>
<field name="val2" control="textbox" datatype="number">
<label>Val 2</label>
</field>
<field name="score" control="textbox" datatype="number">
<label>Score</label>
<calculate>[val1]+[val2]</calculate>
</field>
</form>
When a form is requested, the system will need to pick up the xml, loop through all the fields and generate an angular style html to be served to the browser and processed by angular. Ideally, I want to keep all the form specific logic (validation, show/hide, calculation etc) confined to the html, and keep the controller (js) logic generic for all forms.
The only solution I can come up with is to dynamically load watcher functions, through something like this: eval("$scope.$watch('[data.val1,data.val2]')..."), but as I said, I really want to avoid this, because it's just tedious, and feels extremely dodgy :)
The first dirty way.
In your case you can move all logic from controller into html with using combination of ng-init and ng-change directives.
<div class="form-group">
<label for="val1" class="control-label">Val 1</label>
<input class="form-control" name="val1" type="number" ng-model="data.val1" ng-change="data.score = data.val1 + data.val2" id="val1">
</div>
<div class="form-group">
<label for="val2" class="control-label">Val 2</label>
<input class="form-control" name="val2" type="number" ng-model="data.val2" ng-change="data.score = data.val1 + data.val2" id="val2">
</div>
<div class="form-group" ng-init="data.score = data.val1 + data.val2">
<label for="score" class="control-label">Score</label>
<input class="form-control" name="score" ng-model="data.score" type="text" id="score">
</div>
<br/>data: {{data}}
I don't think that it's the clearest solution, but you can leave your controller without any changes with it.
Demo on plunker.
The second dirty way.
There is one more way, but now you don't need ng-init and ng-change directives. You can add just one dirty expression in html:
<div id="main-container" class="container" style="width:100%" ng-controller="MainController">
{{data.score = data.val1 + data.val2;""}} <!-- key point -->
<div class="form-group">
<label for="val1" class="control-label">Val 1</label>
<input class="form-control" name="val1" type="number" ng-model="data.val1" id="val1">
</div>
<div class="form-group">
<label for="val2" class="control-label">Val 2</label>
<input class="form-control" name="val2" type="number" ng-model="data.val2" id="val2">
</div>
<div class="form-group">
<label for="score" class="control-label">Score</label>
<input class="form-control" name="score" ng-model="data.score" type="text" id="score">
</div>
<br/>data: {{data}}
;"" in expression stops evaluating of angular expression to text in html.
Demo on plunker.
See if this works, in your HTML change,
<input class="form-control" name="score" ng-model = "data.score" type="text" id="score">
and, in your controller do,
var myApp = angular.module('myapp', [])
.controller('MainController', function($scope) {
$scope.data = { val1: 1, val2: 2, score: 3};
$scope.$watch('[data.val1,data.val2]', function (newValue, oldValue) {
$scope.data.score = newValue[0] + newValue[1];
}, true);
})
Demo plunk, http://plnkr.co/edit/gS0UenjydgId4H5HwSjL?p=preview
If you want to know how you can do it, then i have one solution for you make a ng-change event for both of your text box and sum both the number there and use ng-model in the third text box then, you can see it will work as per your need.
For the first time load you need to calculate it out side only.

Resources