Question: How do you clear a dynamically created ng-repeat AngularJS form field? If you can find a place I didn't look for the answer to this, I'd be surprised.
Background: I have AngularJS pulling JSON through a Service into my controller. I then use scope to ng-repeat labels for a form. I am having trouble clearing the fields. Since words don't accurately tell you what I am doing here is the basic code setup. I hacked it down to a few lines.
I've tried the old $scope.formName.inputName=""; and $scope.inputName="";, but they don't work. Any ideas or a direction to go?
http://plnkr.co/edit/BtID7a8EnyxuxClwdHkS?p=preview
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
<link href="style.css" rel="stylesheet" />
<script src="app.js"></script>
</head>
<body ng-app="app" ng-controller="AppTest as app">
<form name="formName" id="formName" style="width: 320px">
<div ng-repeat="item in currentInfo.attribute">
<div style="float:left;">{{item.desc}} </div>
<div style="float:left;">
<input name="forminput" ng-model="forminput" style="width:200px" type="text" value=""/>
</div>
</div>
<button value="Clear" style="float:left;" ng-click="clearMe()">Clear</button>
</form>
</body>
</html>
var app = angular.module("app", []);
app.controller("AppTest", function($scope) {
$scope.currentInfo = {
"attribute": [
{
"name": "ACCT",
"desc": "Account #",
},
{
"name": "FNAME",
"desc": "First Name",
"type": "VARCHAR",
"validation": "^[a-zA-Z\\s]+"
},
{
"name": "LNAME",
"desc": "Last Name",
"type": "VARCHAR",
"validation": "^[a-zA-Z\\s]+"
},
{
"name": "MNAME",
"desc": "Middle Name",
"type": "CHAR",
"validation": "^[a-zA-Z]+[1-9]+"
}
]
};
$scope.clearMe = function (){
$scope.forminput = "";
};
});
You are repeating a single ngmodel="forminput" use unique for each by making forinput an object and creating unique models with keys ng-model="forminput[item.desc]"
first in your controller
$scope.forminput = {};
then in view, change input as
Demo:
// Code goes here
var app = angular.module("app", []);
app.controller("AppTest", function($scope) {
$scope.forminput = {};
$scope.currentInfo = {
"attribute": [
{
"name": "ACCT",
"desc": "Account #",
},
{
"name": "FNAME",
"desc": "First Name",
"type": "VARCHAR",
"validation": "^[a-zA-Z\\s]+"
},
{
"name": "LNAME",
"desc": "Last Name",
"type": "VARCHAR",
"validation": "^[a-zA-Z\\s]+"
},
{
"name": "MNAME",
"desc": "Middle Name",
"type": "CHAR",
"validation": "^[a-zA-Z]+[1-9]+"
}
]
};
$scope.clearMe = function (){
console.log("herleme")
$scope.forminput = {};
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="app" ng-controller="AppTest as app">
<h1>Hello Plunker!</h1>
<form name="formName" id="formName">
<div ng-repeat="item in currentInfo.attribute">
<div style="float:left;">{{item.desc}} </div>
<div > <input name="forminput[item.desc]" ng-model="forminput[item.desc]" style="width:200px" type="text" value=""/>
</div>
</div>
<button value="Clear" ng-click="clearMe()">Clear</button>
</form>
</body>
<input name="forminput[item.desc]"
ng-model="forminput[item.desc]"
style="width:200px" type="text" value=""/>
and clearing it as
$scope.clearMe = function (){
console.log("herleme")
$scope.forminput = {};
};
If I understand, you want to clear all fields in the form on clicking the 'clear' button?
Here's a working version:
http://plnkr.co/edit/f0QSDKH7qkM8CcZRU5Js?p=preview
var app = angular.module("app", []);
app.controller("AppTest", function($scope) {
$scope.currentInfo = {
"attribute": [
{
"name": "ACCT",
"desc": "Account #",
},
{
"name": "FNAME",
"desc": "First Name",
"type": "VARCHAR",
"validation": "^[a-zA-Z\\s]+"
},
{
"name": "LNAME",
"desc": "Last Name",
"type": "VARCHAR",
"validation": "^[a-zA-Z\\s]+"
},
{
"name": "MNAME",
"desc": "Middle Name",
"type": "CHAR",
"validation": "^[a-zA-Z]+[1-9]+"
}
]
};
$scope.clearMe = function (){
for(var i = 0; i < $scope.currentInfo.attribute.length; i++) {
$scope.currentInfo.attribute[i].forminput = '';
}
};
});
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
<link href="style.css" rel="stylesheet" />
<script src="app.js"></script>
</head>
<body ng-app="app" ng-controller="AppTest as app">
<h1>Hello Plunker!</h1>
<form name="formName" id="formName">
<div ng-repeat="item in currentInfo.attribute">
<div style="float:left;">{{item.desc}} </div>
<div style="float:left;"> <input name="forminput" ng-model="item.forminput" style="width:200px" type="text" value=""/>
</div>
</div>
<button value="Clear" ng-click="clearMe()">Clear</button>
</form>
</body>
</html>
I've used the currentInfo model itself to bind the value of the inputs. This means they'll be available outside of the scope of the ng-repeat. Then the clear function iterates through each item in the 'attributes' array and sets the value to empty string.
You were on the right path, but with slight bug. All of the generated forms were bind to same model - forminput. You have to generate model binding dynamically.
<input name="forminput" ng-model="formmodel[item.name]"/>
and in the controller
$scope.formmodel = {};
check out the plunkr
Also, for generated forms check out projects as autofields, no need to reinvent the wheel.
Related
I am trying to add checkboxes to every name, and then add a boolean to $scope.messages at the name : ex. I check checkbox at name eva - then $scope.messages looks like that :
$scope.messages =
{
"family": [
{
"name": "eva",
"checked" : true,
"childrens" : [..
Here is my code :
JS:
$scope.messages =
{
"family": [
{
"name": "eva",
"childrens": [
{
"name": "John",
"childrens": [
{
"name": "Jacob"
}
]
}
]
},
{
"name": "ben",
"childrens": [
{
"name": "Eva",
"childrens": [
{
"name": "Jack"
}
]
}
]
}
]
}
HTML :
<div ng-repeat="key in messages">
<ul ng-repeat=" (x, y) in key" style="list-style:none;">
<li><input type="checkbox" ng-model="shapes" ng-change="changeValue(shapes, y.name)"/> {{y.name}}</li>
<li style="margin-left:15px;" ng-repeat="(a,b) in y.childrens" ><input type="checkbox" ng-model="shapes" ng-change="changeValue(shapes, b.name)"/> {{b.name}}
<ul style="margin-left:15px;" ng-repeat="p in b.full_name" >
<li><input type="checkbox" ng-model="shapes" ng-change="changeValue(shapes, p.name)"/> {{p.name}}</li>
</ul>
</li>
</ul>
</div>
Also i would like to add boolean to children of checked name
ex.
$scope.messages =
{
"family": [
{
"name": "eva",
"checked" : true,
"childrens": [
{
"name": "John",
"checked" : true,
"childrens": [
{
"name": "Jacob",
"checked" : true,
}
Here is my plunker : http://plnkr.co/edit/CbOrL5l4o7a2f9OOjZ2w?p=preview
Thanks for answers in advance!!!
I am not sure I have understood the question or what exactly you need but I have played around with your code a bit and now I can see the 'checked' boolean value for each item in the family tree.
Checkout my code and see if this is the direction you were looking for.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.messages =
{
"family": [
{"name": "eva",
checked: false,
"childrens":
[
{"name": "John",
checked: false,
"childrens": [
{"name": "Jacob", checked: false}
]
}
]
},
{"name": "ben",
checked: false,
"childrens":
[
{"name": "Eva",
checked: false,
"childrens": [
{"name": "Jack", checked: false}
]
}
]
}
]
}
$scope.changeValue = function(item) {
console.log(item.name);
console.log(item.checked);
};
});
I have adjusted the HTML a bit as well:
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div ng-repeat="key in messages">
<ul ng-repeat="person in key" style="list-style:none;">
<li>
<input type="checkbox" ng-model="person.checked" ng-change="changeValue(person)"/> {{person.name}}
</li>
<li style="margin-left:15px;" ng-repeat="child in person.childrens" >
<input type="checkbox" ng-model="child.checked" ng-change="changeValue(child)"/> {{child.name}}
<ul style="margin-left:15px;" ng-repeat="grandChild in child.childrens" >
<li>
<input type="checkbox" ng-model="grandChild.checked" ng-change="changeValue(grandChild)"/> {{grandChild.name}}
</li>
</ul>
</li>
</ul>
</div>
</body>
If you open the console, you will see the name and the checkbox value for the item you have clicked. It is better to use object field with ng-model.
2 options:
what is better for performance and watchers using, now I am using the first option and I would like to improve performance
the object today looks like:
message = {
message : X,
}
and I would like to do somthing like :
obj = {
text : text,
icon: "src.png"
status: X,
class : "className",
color: "color_code_like_#ffff"
}
1 :
<div ng-if="message.message == 0" class="classA" style="">
<span class="same"><img class="sameClass" ng-src="a.gif"></span>
<span class="status-text a_with_animation" style="color:red;">textA</span>
</div>
<div ng-if="message.message == 1" class="classB" style="">
<span class="same"><img class="sameClass" ng-src="b.png"></span>
<span class="status-text" style="color:blue;">textB</span>
</div>1
<div ng-if="message.message == 2" class="classC" style="">
<span class="same"><img class="sameClass" ng-src="c.png"></span>
<span class="status-text" style="color:black;">TextC</span>
</div>
option 2
<div class="{{obj.class}}" style="">
<span class="same"><img class="sameClass" ng-src="{{obj.class}}"></span>
<span class="status-text {{obj.animation}" style="color:red;">
{{obj.text}}</span>
</div>
also all the data here is two way binding
Not really pretty but I made an example of how you could populate your data with ng-include template. Here is a demo:
<!DOCTYPE html>
<html ng-app="myApp">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-controller="myCtrl">
<select ng-model="message" ng-change="change()" ng-options="x.message for x in messages">
</select>
<br>
ngInclude: <div ng-include="'abc.html'"></div>
Directive: <div temp-directive></div>
<!-- A separate file for the template -->
<script type="text/ng-template" id="abc.html">
<div class="{{obj.class}}" style="">
<span class="same"><img class="sameClass" ng-src="{{obj.icon}}"></span>
<span class="status-text {{obj.animation}}" ng-style="obj.style">
{{obj.text}}</span>
</div>
</script>
</div>
<script>
var app = angular.module('myApp', []);
app.directive("tempDirective", function() {
return {
template : "<div class='{{obj.class}}' style=''><span class='same'><img class='sameClass' ng-src='{{obj.icon}}'></span><span class='status-text {{obj.animation}}' ng-style='obj.style'> {{obj.text}}</span></div>"
};
});
app.controller('myCtrl', function($scope) {
$scope.messages = [{
"message": 0
}, {
"message": 1
}, {
"message": 2
}];
$scope.message = $scope.messages[0]; // initialise
$scope.objects = [{
"text": "Message - 0",
"icon": "a.gif",
"animation": "a_with_animation",
"class": "classA",
"style": {
"color": "#00aaaa"
}
}, {
"text": "Message - 1",
"icon": "b.png",
"animation": "",
"class": "classB",
"style": {
"color": "#aa00aa"
}
}, {
"text": "Message - 2",
"icon": "c.png",
"animation": "",
"class": "classC",
"style": {
"color": "#aaaa00"
}
}];
$scope.obj = $scope.objects[0]; // initialise
$scope.change = function() { // changing the template data
$scope.obj = $scope.objects[$scope.message.message];
}
});
</script>
</body>
</html>
[Note]: it is best to replace ng-include with a component / directive with their template (not templateUrl) for performance improvement, since it is asynchronous and takes time to load the HTML
I have json output from api wants to display in ng-repeat on div
[
{
"companyName": "abc",
"namesList": [
{
"name": "Jaakr1",
"email": "poonam.kumar#abc.com",
"job": "Developer 1"
},
{
"name": "janam1",
"email": "raja#abc.com",
"job": "Developer 2"
}
]
}
]
I want to display like this
<div class="list-row">
<div class="list-cell">abc</div>
<div class="list-cell">Jaakr1</div>
<div class="list-cell">poonam.kumar#abc.com</div>
<div class="list-cell">Developer 1</div>
</div>
<div class="list-row">
<div class="list-cell"></div>
<div class="list-cell">janam1</div>
<div class="list-cell">raja#abc.com</div>
<div class="list-cell">Developer 2</div>
</div>
Please provide the solution
Apart from all the answers posted above i would like to post mine that will handle multiple JSON objects inside the array. Since you have only one object right now one of the above solution may work but when you have more that one object inside the array then this will work great.
HTML
<div ng-app='app' ng-controller='mainCtrl'>
<div ng-repeat="(key1, value1) in data">
<div class="list-row" ng-repeat="(key2, value2) in data[key1].namesList">
<div class="list-cell"><span ng-if='$index == 0'>{{data[key1].companyName}}</span> </div>
<div class="list-cell">{{value2.name}}</div>
<div class="list-cell">{{value2.email}}</div>
<div class="list-cell">{{value2.job}}</div>
</div>
</div>
</div>
Controller
angular.module('app',['QuickList']).controller('mainCtrl', function($scope){
$scope.data = [
{
"companyName": "abc",
"namesList": [
{
"name": "Jaakr1",
"email": "poonam.kumar#abc.com",
"job": "Developer 1"
},
{
"name": "janam1",
"email": "raja#abc.com",
"job": "Developer 2"
}
]
},
{
"companyName": "abc2",
"namesList": [
{
"name": "Jaakr12",
"email": "poonam.kumar#abc.com2",
"job": "Developer 12"
},
{
"name": "janam12",
"email": "raja#abc.com2",
"job": "Developer 22"
}
]
}
];
})
For more generalization i have added two JSON objects inside the array and the output is exactly what you expected. To play around i have added the JSFIDDLE
<div *ngFor="let person of jsonObj.namesList">
<div class="list-cell"></div>
<div class="list-cell">{{ person.name }}</div>
<div class="list-cell">{{ person.email }}</div>
<div class="list-cell">{{ person.job}}</div>
</div>
You can do this,
<div ng-repeat="item in myArray[0].namesList" class="list-row">
<div class="list-cell">{{item.name}}</div>
<div class="list-cell">{{item.email}}</div>
<div class="list-cell">{{item.job}}</div>
</div>
DEMO
var myApp = angular.module('ReqWebApp', [])
myApp.controller('ReqAppController', function ReqAppController($scope) {
$scope.myArray = [
{
"companyName": "abc",
"namesList": [
{
"name": "Jaakr1",
"email": "poonam.kumar#abc.com",
"job": "Developer 1"
},
{
"name": "janam1",
"email": "raja#abc.com",
"job": "Developer 2"
}
]
}
];
});
<!DOCTYPE html>
<html ng-app="ReqWebApp">
<head>
<meta charset="UTF-8">
<title>New Request</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body ng-controller="ReqAppController">
<div ng-repeat="item in myArray[0].namesList" class="list-row">
<div class="list-cell">{{item.name}}</div>
<div class="list-cell">{{item.email}}</div>
<div class="list-cell">{{item.job}}</div>
</div>
</body>
</html>
You can do something like this:
<div class="list-row" ng-repeat="nameObj in data.namesList">
<div class="list-cell">{{data.companyName}}</div>
<div class="list-cell">{{nameObj.name}}</div>
<div class="list-cell">{{nameObj.email}}</div>
<div class="list-cell"{{nameObj.job}}</div>
</div>
This is my JSON data:
[
{
"name": "elin",
"family": "kinoian"
},
{
"name": "simon",
"family": "santos"
},
{
"name": "sara",
"family": "pinki"
},
{
"name": "emin",
"family": "richard"
}
]
As you can see,I have 2 key in each row "name" and "family.
This is my ng-repeat filtering by json object "search":
<li ng-repeat="membr in familyMember| filter:search">
<span> {{membr.name}} - {{membr.family}}</span>
</li>
And these are my inputs for filtering:
By name: <input type="text" ng-model="search.name1">
and <input type="text" ng-model="search.name2">
By family: <input type="text" ng-model="search.family">
I need the rows which name is "elin" and "sara". I`m looking for "AND Condition" in filtering. How can I do that?
First of all, no, you're not looking for an AND condition, but for an OR. Indeed, a family member can't be named "elin" and "sara" at the same time.
Now, if you read the documentation for the filter filter, you'll see that it accepts a function as argument, which must return a truthy value if the value is accepted, and a truthy value if it's rejected. So all you need is
ng-repeat="member in familyMember| filter:isAccepted">
and
$scope.isAccepted = function(member) {
return member.name === $scope.search.name1 || member.name === $scope.search.name2;
}
You need to use a custom filter with OR condition.
$scope.nameFilter = function(member) {
var result = (member.name == $scope.membr.name1) ||
(member.name == $scope.membr.name2) ||
(member.family == $scope.membr.family);
return result;
};
DEMO
var myApp = angular.module('myApp', []);
myApp.controller("MyCtrl", ['$scope', function($scope) {
$scope.familyMember = [{
"name": "elin",
"family": "kinoian"
}, {
"name": "simon",
"family": "santos"
}, {
"name": "sara",
"family": "pinki"
}, {
"name": "emin",
"family": "richard"
}];
$scope.nameFilter = function(member) {
var result = (member.name == $scope.membr.name1) ||
(member.name == $scope.membr.name2) ||
(member.family == $scope.membr.family);
return result;
};
}]);
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#1.4.7" data-semver="1.4.7" src="https://code.angularjs.org/1.4.7/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div ng-app="myApp" ng-controller="MyCtrl">
By name:
<input type="text" ng-model="membr.name1" > and
<input type="text" ng-model="membr.name2"> By family:
<input type="text" ng-model="membr.family">
<li ng-repeat="membr in familyMember| filter:nameFilter">
<span> {{membr.name}} - {{membr.family}}</span>
</li>
</div>
</body>
</html>
Try this working demo :
var app = angular.module('myApp',[]);
app.controller('mainCtrl', function($scope) {
$scope.familyMember = [
{
"name": "elin",
"family": "kinoian"
},
{
"name": "simon",
"family": "santos"
},
{
"name": "sara",
"family": "pinki"
},
{
"name": "emin",
"family": "richard"
}
];
$scope.search = function(membr) {
return membr.name === $scope.search.name1 || membr.name === $scope.search.name2;
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='myApp' ng-controller='mainCtrl'>
name1: <input type="text" ng-model="search.name1">
name2: <input type="text" ng-model="search.name2"><br><br>
<li ng-repeat="membr in familyMember | filter:search">
<span> {{membr.name}} - {{membr.family}}</span>
</li>
</div>
I'm trying to create a new array from an exiting array of parameters with AngularJS.
Explaining better:
I have an array of parameters:
"parameters": [
{"id":2,"exibitionName":"gaps","name":"--gaps","description":"Nº de GAPS permitido","defaultValue":null},
{"id":4,"exibitionName":"Block Size","name":"--block-size","description":"Tamanho dos blocos","defaultValue":null}
]
With this array I create with ng-repeat a set of inputs to take the respective value of each parameter from the user:
<div class='row well well-sm' ng-show='selectedAlg'>
<div class='col-md-3' ng-repeat='parameter in selectedAlg.parameters'>
<label class="control-label">{{parameter.exibitionName}}</label>
<input class="form-control input-sm" type="text">
</div>
</div>
In the end I want to have another array of parameters with this structure:
"parameters": [
{paramName:"--threads", paramValue:"18"},
{paramName:"--gaps", paramValue:"2"}
]
What directives I need to use in the input to take the value and build this new structure I want?
I tried you requirement with ng-change directive in the input tag and kept one button to generate your end array when you click that button.
Take a look at the code,
<html ng-app="myApp">
<head>
<script data-require="angular.js#1.3.15" data-semver="1.3.15" src="https://code.angularjs.org/1.3.15/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="myController">
<div ng-show='selectedAlg'>
<div ng-repeat="parameter in selectedAlg.parameters">
<label>{{parameter.exibitionName}}</label>
<input id="{{$index}}" ng-model="val" type="text" ng-change="insertArray = $index==selectedAlg.parameters.length-1?true:false;
setParamvalues(val, insertArray)"></input>
</div>
<button type="button" ng-click="constructArray();">Construct Array</button>{{endArray}}
</div>
</body>
</html>
Here is the controller,
var app = angular.module('myApp', []);
app.controller('myController', function($scope) {
$scope.endArray = [];
$scope.selectedAlg = {
"parameters": [
{
"id": 2,
"exibitionName": "gaps",
"name": "--gaps",
"description": "Nº de GAPS permitido",
"defaultValue": null
},
{
"id": 4,
"exibitionName": "Block Size",
"name": "--block-size",
"description": "Tamanho dos blocos",
"defaultValue": null
}
]
};
$scope.setParamvalues = function(values, insertArray) {
if(!insertArray) {
$scope.paramName = values;
}
if(insertArray) {
$scope.paramValue = values;
}
}
$scope.constructArray = function() {
$scope.endArray.push({
paramName: $scope.paramName,
paramValue: $scope.paramValue
});
}
});
Working plunker
Hope this helps!