Directives inside ng-repeat to create a new structure with AngularJS - arrays

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!

Related

angular ng-repeat array show only one element

I have an array like this
$scope.mentors = [ {"name":"Jonathan", "status":0},
{"name": "Nathan","status":1},
{"name": "Chris","status":1},
{"name": "Brian","status":0}];
here my view code
<div ng-repeat="m in mentors">
<div ng-if="m.status == '1'">
<div>
{{m.name}}
</div>
</div>
</div>
and my result is :
Nathan and Chris
what can I do to just make it show Nathan or Chris
it must only show one result only
p/s: already try ng-show="$last" it did not work since Brian status is '0'
You can filter the array on statuses and then just take the first by checking against $index
angular.module('app', []).controller('myCtrl',function($scope){
$scope.mentors = [ {"name":"Jonathan", "status":0},
{"name": "Nathan","status":1},
{"name": "Chris","status":1},
{"name": "Brian","status":0}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html>
<body ng-app="app">
<div ng-controller="myCtrl">
<div ng-repeat="m in mentors | filter : {status: 1}">
<div ng-if="$index == 0">
<div>
{{m.name}}
</div>
</div>
</div>
</div>
</body>
</html>
You could use the limitTo and filter
<div ng-repeat="m in mentors | filter: { status : '1'}| limitTo : 1">
<div>
{{m.name}}
</div>
</div>
There is no reason to use ng-repeat if you only need to display 1 item.
You should handle this in your controller. Create a new variable that will hold the mentor that you want to show.
To find Nathan, you can use Array#find(). It will return the first item that matches the condition status === 1
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.mentors = [{
"name": "Jonathan",
"status": 0
},
{
"name": "Nathan",
"status": 1
},
{
"name": "Chris",
"status": 1
},
{
"name": "Brian",
"status": 0
}
];
$scope.mentor = $scope.mentors.find(m => m.status === 1);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<h1>{{mentor.name}}</h1>
</div>

AngularJS ng-repeat filtering JSON error

I'm learning about AngularJS and I have an error in Chrome console when I do this:
<input ng-model="search" />
<ul>
<li ng-repeat="prof in profesores | filter:search">
{{prof.nombre}} - {{prof.telefono}}
</li>
</ul>
with this data "profesores":
{
"profesores": [
{
"id": 0,
"sexo": "hombre",
"nombre": "Kari",
"snombre": "Carr",
"telefono": "(826) 453-3497",
"celular": "(801) 9175-8136"
},
{
"id": 1,
"sexo": "mujer",
"nombre": "Tameka",
"snombre": "Gamble",
"telefono": "(824) 438-2499",
"celular": "(801) 8595-8337"
} ]
}
The error is this:
The code works correctly (filter the items with string in input) but I have the error in console. What am I doing wrong?
Here ng-repeat="prof in profesores | search" --> wrong
ng-repeat="prof in profesores |filter: search" --> right
var myApp = angular.module('myApp',[]);
myApp.controller('samplecontroller', function($scope) {
$scope.profesores = [
{
"id": 0,
"sexo": "hombre",
"nombre": "Kari",
"snombre": "Carr",
"telefono": "(826) 453-3497",
"celular": "(801) 9175-8136"
},
{
"id": 1,
"sexo": "mujer",
"nombre": "Tameka",
"snombre": "Gamble",
"telefono": "(824) 438-2499",
"celular": "(801) 8595-8337"
}
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!doctype html>
<html >
<head>
</head>
<body ng-app="myApp">
<div ng-controller="samplecontroller">
<input ng-model="search" />
<ul>
<li ng-repeat="prof in profesores |filter: search">
{{prof.nombre}} - {{prof.telefono}}
</li>
</ul>
</div>
</body>
</html>
Initialiae it with an empty array like this when js loads:
$scope.profesores = []
Then you can define the variable again in your promise :
$http.get('json/profesores.json') .success(function(data){ $scope.profesores = data.profesores; });
Until the data is loaded from the server your profesores variable is undefined and will throw the error. Initialize it with an empty array at the beginning o your controller:
$scope.profesores = [];
After that you can request the data and fill the array:
$http.get('json/profesores.json').success(function(response){
$scope.profesores = response.profesores;
});

How to clear dynamic ng-repeat form fields

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.

when I put ng-controller in div instead of body autocomplete stops working

I have a textbox with autocomplete capability and after clicking on click me button the text in autocomplete is added as in the table , here is the link that works perfectly fine,
var app = angular.module('app', []);
app.factory('Service', function() {
var typesHash = [ {
id :1,
name : 'lemon',
price : 100,
unit : 2.5
}, {
id : 2,
name : 'meat',
price : 200,
unit : 3.3
} ];
var localId = 3;
availableTags = [
"ActionScript",
"AppleScript",
"Asp",
"BASIC",
"C",
"C++",
"Clojure",
"COBOL",
"ColdFusion",
"Erlang",
"Fortran",
"Groovy",
"Haskell",
"Java",
"JavaScript",
"Lisp",
"Perl",
"PHP",
"Python",
"Ruby",
"Scala",
"Scheme"
];
var service = {
addTable : addTable,
getData : getData,
complete:complete
};
return service;
function complete($scope){
$( "#txt" ).autocomplete({
source: availableTags,
messages: {
noResults: '',
results: function() {}
}
});
$("#txt" ).on( "autocompleteselect", function( event, ui ) {
$scope.tableTools.inputData=ui.item.value;
} );
}
function addTable(name,price) {
typesHash.push({id:localId++, name:name, price:price,unit:1});
}
function getData() {
return typesHash;
}
});
app.controller('table', function(Service,$scope) {
//get the return data from getData funtion in factory
this.typesHash = Service.getData();
//get the addtable function from factory
this.addTable = Service.addTable;
this.complete=Service.complete($scope);
});
working link
but as soon as I put ng-controller="table as tableTools" in the div instead of body then autocompleting of text box start acting funny and it does not work properly
not working link
can anyone explain the reason and tell me how I can fix it in a way that even by putting ng-controller="table as tableTools" inside div it works?
Update:
here is the error:
Uncaught TypeError: Cannot set property 'inputData' of undefined
for this line:
$scope.tableTools.inputData = ui.item.value;
(remember the problem starts after you click on suggested text)
The issue is hidden in missunderstanding of the angularjs object life-cycles.
The most important here to know is:
services (factory/provider ... different creation, but at the end the same) are singletons
controllers are instantiated per each view. (There are many, multi instances of one controller through the angular app life time..)
So what happened?
There is one service:
app.factory('Service', function() {
...
and there is one controller passing its scope into that service
app.controller('table', function(Service,$scope) {
...
this.complete=Service.complete($scope);
And on the page we can see:
// first usage of controller
// its first instance is created, $scope is passed
<div class="row commonRow" ng-controller="table as tableTools">
// second usage
// different instance is created... and it also passes the §scope
<tbody ng-controller="table as iterateTb">
But as described above - service is only one. While first controller passes its $scope, the second does after while as well.. and that is causing the issue.
We can use services inside of controllers. That is the design principle of angular. But we should not pass the $scope...
This is happening because you have two controller on the same page with two differenct element therefore scope is not binding properly.
The best code for you to do this is :-
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<link data-require="bootstrap#*" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">
<title>Insert title here</title>
<script>
var app = angular.module('app', []);
app.factory('Service', function() {
var typesHash = [ {
id :1,
name : 'lemon',
price : 100,
unit : 2.5
}, {
id : 2,
name : 'meat',
price : 200,
unit : 3.3
} ];
var localId = 3;
availableTags = [
"ActionScript",
"AppleScript",
"Asp",
"BASIC",
"C",
"C++",
"Clojure",
"COBOL",
"ColdFusion",
"Erlang",
"Fortran",
"Groovy",
"Haskell",
"Java",
"JavaScript",
"Lisp",
"Perl",
"PHP",
"Python",
"Ruby",
"Scala",
"Scheme"
];
var service = {
addTable : addTable,
getData : getData,
complete:complete
};
return service;
function complete($scope){
$( "#txt" ).autocomplete({
source: availableTags,
messages: {
noResults: '',
results: function() {}
}
});
$("#txt" ).on( "autocompleteselect", function( event, ui ) {
console.log($scope);
$scope.tableTools.inputData=ui.item.value;
} );
}
function addTable(name,price) {
typesHash.push({id:localId++, name:name, price:price,unit:1});
}
function getData() {
return typesHash;
}
});
app.controller('table', function(Service,$scope) {
//get the return data from getData funtion in factory
this.typesHash = Service.getData();
//get the addtable function from factory
this.addTable = Service.addTable;
this.complete=Service.complete($scope);
});
</script>
</head>
<body ng-app="app" ng-controller="table as tableTools" >
<form >
<div class="row commonRow" >
<div class="col-xs-1 text-right">
item:
</div>
<div class="col-xs-5">
<input id="txt" type="text" style="width: 100%;" ng-keyup="tableTools.complete()" ng-model="tableTools.inputData">
</div>
<div class="col-xs-2">
<button class="btn btn-primary" ng-click="tableTools.addTable(tableTools.inputData);tableTools.inputData=''">
click me
</button>
</div>
</div>
</form>
<div class="row commonRow">
<div class="col-xs-1"></div>
<div class="col-xs-10">
<table class="table table-hover">
<thead>
<tr>
<th>item</th>
</tr>
</thead>
<tbody> <!--No need for controller here-->
<tr ng-repeat="x in tableTools.typesHash track by x.id">
<td>
<div>{{x.name}}</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>
Plunker
If you add
$scope.tableTools={}
right below
function complete($scope){
the second one works as expected.
can anyone explain the reason
As long as the object ‘$scope.tableTools‘ has not been defined, you cannot successfully add attributes to it

How can I get filtered data objects from AngularJS?

i have trouble to figure out how i can receive the filtered data after the change event took place. My code structure looks like the following. THe alert is fired but how to move on?
<html ng-app>
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script>
</head>
<body ng-controller="List">
Search: <input ng-change="getData()" ng-model="query">
Search: <select ng-change="getData()" ng-model="query2">
<option></option>
<option>Berlin</option>
<option>Hamburg</option>
</select>
<div>
<ul class="names" >
<li ng-model="item" " ng-repeat="name in names | filter:query | filter:query2">
{{name.firstname}}, {{name.lastname}}, {{name.age}}, {{name.location}}
</li>
</ul>
</div>
<script type="text/javascript">
function List($scope) {
$scope.names = [
{"firstname": "Carl",
"lastname": "Luyk",
"age": 20,
"location":"Berlin"},
{"firstname": "Carl",
"lastname": "Moreen",
"age": 20,
"location":"Hamburg"},
{"firstname": "Tom",
"lastname": "Luyk",
"age": 25,
"location":"New York"},
{"firstname": "Caren",
"lastname": "Tilt",
"age": 20,
"location":"Paris"},
{"firstname": "Caren",
"lastname": "Orail",
"age": 30,
"location":"Hamburg"},
];
$scope.getData= function(){
//here I would like to get the data structured like $scope.names..is that possible?
alert('changed');
}
}
</script>
</body>
</html>
Try this:
Search: <input ng-change="getData(names, query)" ng-model="query">
And inside your Controller:
$scope.getData = function (names, query) {
$scope.queryData = $filter('filter')(names, query));
};
So $scope.queryData is now your results collection.
The reason you're getting "$filter is underfined" is because you haven't injected it into your controller. When you define your controller, do:
app.controller('list', function($scope, $filter) {
$scope.getData = function (names, query) {
$scope.queryData = $filter('filter')(names, query));
};
}
You can also define your search in your controller.
$scope.queryData = $filter('filter')(array, search-expression));
Hope that helps!

Resources