Angular : pass mutliple values to the controller - angularjs

Let's say i have a drop drown list that i add dynamicly in my html template:
<button type="button" ng-click="addRow()" style="margin-bottom:5px;">Add cities </button>
<div ng-repeat="city in cities">
<select ng-model="cities_$index"
ng-options="n.id as n.name for n in citiesList"
class="form-control"
ng-required="true">
<option value="">-- Choose City --</option>
</select>
</div>
Angular Controller :
$scope.addRow = function () {
var newrow = [];
if ($scope.cities.length === 0) {
newrow.push({ 'cities': $scope.cities_0 });
}
else {
$scope.cities.forEach(function (row, key) {
var city= '$scope.cities_'+key; // in php i can do this
//but i dont know how to do it with Js/Angular
console.log('row' + city);
newrow.push({ 'cities': city});
console.log(newrow);
});
}
$scope.cities.push(newrow);
}
I tried this to retrieve the values from the cities selected but i have undefined values.
$scope.send = function () {
angular.forEach($scope.cities, function (value, key) {
console.log(value.id); // the id from the ng-options
};
In a regular html code i just add name="city" and i retrieve all the cities added in my input box. But how i can retrieve thoses cities from the ng-model in my controller ?
I know i'm doing something wrong, but since i'm new with angular i'm trying !!
Thank you

supposing that the key (city) is inside your datas array, you can do :
<div ng-repeat="data in datas">
<input type="text">{{data.name}}
</div>

ng-model is still unique. What you are missing here is that ng-repeat creates a child scope for each item. Therefore, the value of ng-model is unique for EACH child scope. ng-model doesn't behave the same way as plain HTML input and having multiple inputs with the same ng-model will only point to the same object in memory. And not, "add up" values to the property city as you would expect in plain HTML inputs.
If you are using the object datas in your ng-repeat, it's kind of common practice that your <input /> would bind to a item property of datas.
<div ng-repeat="data in datas">
<input type="text">{{data.city}}
</div>

Related

Based on dropdown value show div inside ng-repeat

The below thing is taking too much time than expected. Been through top stack solutions and somehow got the below thing--
WHAT IS THE SCENERIO
I have an ng-repeat div with dropdown.
The drop down contains values and based on selection of those values a div will be shown. What I managed is div is shown. But when I choose another item the previous item div gets hidden.
Below are the screen shot and my code
As it can be seen that when I select the first item it shows the textbox div. But when I select the next item the first gets hidden. There are essentially two values -- ALL, Fixed. When All selected nothing will be shown and when Fixed is selected the div for that particular item will be shown.
HTML code
<div class="tst text-success" ng-repeat="(parentIndex, catList) in categoryArray">
<div class="col-md-3">
{{catList.categoryName}}
</div>
<div class="col-md-4">
<select class="form-control m-b" ng-model="catObj.cats" ng-change="changeOption(catObj,parentIndex)">
<option value="All">All</option>
<option value="fixed">Fixed No. Of Records</option>
<option value="perfixed">% od Fixed</option>
</select>
</div>
<div class="col-md-3 noPad" ng-if="isShowing==parentIndex">
<input type="text" class="form-control form-control-small" placeholder="Set Number" />
</div>
</div>
CONTROLLER
$scope.changeOption = function(obVal,index) {
console.log(obVal);
console.log(index);
if(obVal.cats == "All") {
//$scope.tbx = 0;
}
else {
$scope.isShowing = index;
}
}
Help would be appreciated
Thanks
You're using a single boolean $scope variable, isShowing, to control the visibility of several divs. That can't possibly work.
You should
have an array of objects, each having a selectedOption field.
use ng-model in your select box to set the selectedOption of the object you're editing.
use the value of the object's selectedOption to know if the additional input should be visible for that object.
Example:
<div ng-repeat="obj in objects">
{{ obj.name }}
<select name="op" ng-model="obj.selectedOption" ng-options="option.value as option.value for option in options"></select>
<input ng-if="obj.selectedOption !== 'All'" />
</div>
app.controller('MainCtrl', function($scope) {
$scope.options = [
{value: 'All'},
{value: 'Fixed'}
];
$scope.objects = [
{name: 'Twitter', selectedOption: 'All'},
{name: 'News', selectedOption: 'Fixed'}
]
});

How to update scope on form Submit, when ng-model value changes?

I am creating an edit customer form and passing an object of 30 key value pairs. I am then using ng-repeat to populate input fields of a form. All form is displayed nicely and with passed key, values. I can also change the value of any input field.But when I submit the form, it takes the old scope object which I passed initially in the form, leaving behind my changes. I need to submit my changed object Now. How To do that? I searched much but can't find the solution to this.
var app = angular.module("customerModule", []);
app.controller('crudController', function($scope, $http) {
$scope.Customers = //object from Ap with almost 30 key,values
$scope.edit = function() {
console.log($scope.Customers);
//the above line prints the API called object where as I am editing the values of ng-model in my form. and I need the form submitted values
}
});
<div ng-app="customerModule" ng-controller="crudController">
<form name="as" ng-submit="edit()">
<ul>
<li ng-repeat="(key, val) in Customers " ng-hide="(key=='total' || key=='paid' || key=='customfields' || key=='owing')" ng-if="key!='customfields'">
<label class="label"> {{key}}</label> <input type="text" ng-model="val" />
</li>
<li ng-repeat="(key, val) in Customers.customfields">
<label class="label"> {{key}}</label> <input type="text" ng-model="val" />
</li>
<button type="submit"><i class="fa fa-plus-circle" aria-hidden="true"></i><span> Edit Customer</span></button>
<ul>
</form>
</div>
Use ng-model="Customer[key]".
You're using the local variable val referencing the value. That's basically aquivalent to doing
var val = Custom['foo'];
val = 'newValue';
That won't change the value of Custom['foo'], right?
But the following will:
Custom['foo'] = 'newValue';

How to remove item from an array

I have a dropdown where items are populated from $scope.role. Now I need to remove the values from $scope.role once the value is added or selected in dropdown. I did splice(index,1) which actually delete the first element only. Need assistance.
$scope.role = ['Actor', 'Director/ Asst. director', 'Lyricist',
'Music director/ Asst. director', 'Singer', 'Standup Comedian', 'Model',
'Cinematographer', 'Photographer', 'Script Writer', 'Choreographer',
'Editor/ Promo editor', 'Costume designer', 'Art director', 'Stunt artist',
'Voice-over artist', 'Graphic Designer', 'Screenplay', 'Dialogue',
'Back ground music'];
Html:
<div class="row newRow">
<div class="form-group fields col-sm-2 col-xs-4">
<label>ROLE *</label>
<select name="role" class="form-control1 drop2" required ng-model="model.role" placeholder="select">
<option value='' disabled selected>Select</option>
<option ng-repeat="item in role track by $index" value="{{item}}">{{item}}</option>
</select>
</div>
<div class="form-group col-sm-2 col-xs-4">
<button ng-click="AddRole()">Click to Add Role</button>
</div>
</div>
JS:
$scope.multiRoles = [];
$scope.role == $scope.dummy;
$scope.rolesAdded = false;
$scope.AddRole = function(index) {
debugger;
if ($scope.model.role !== undefined) {
$scope.multiRoles.push($scope.model.role);
$scope.role.splice(index, 1);
console.log($scope.role);
}
};
You can do it in two ways 1) As suggested by #nikjohn by sending your $index of dropdown in ng-click = "AddRole($index)" and then splice or else
2) You can find the index of the selected option by using the ng-model binded to the dropdown.
$scope.AddRole = function(){
debugger;
if($scope.model.role !== undefined ){
$scope.multiRoles.push($scope.model.role);
var index = $scope.role.indexOf($scope.model.role); //just find the right index which is the selected option in dropdown.
$scope.role.splice(index,1);
console.log($scope.role);
}
};
In your HTML, pass $index to the AddRole. Otherwise, the function does not know what $index is, and also include the button within the ng-repeat:
<select name="role"
class="form-control1 drop2" required
ng-model="model.role" placeholder="select">
<option value='' disabled selected>Select</option>
<option ng-repeat="item in role track by $index" value="{{item}}"> {{item}}
<button ng-click = "AddRole($index)">Click to Add Role</button>
</option>
</select>
In your Controller, there's an extra = that I've highlighted in my comment:
$scope.multiRoles = [];
$scope.role == $scope.dummy; // Why a `==` here? This should be a `=`
$scope.rolesAdded = false;
$scope.AddRole = function(index){
debugger;
if($scope.model.role.length){ // Cleaner method to verify that the array is non-empty
$scope.multiRoles.push($scope.model.role);
$scope.role.splice(index,1);
console.log($scope.role);
}
};
May I also suggest that you use Angular's select implementation with ng-options because:
Choosing between ngRepeat and ngOptions
In many cases, ngRepeat can be used on elements instead of ngOptions to achieve a similar result. However, ngOptions provides some benefits:
more flexibility in how the <select>'s model is assigned via the select as part of the comprehension expression
reduced memory consumption by not creating a new scope for each repeated instance
increased render speed by creating the options in a documentFragment instead of individually
Specifically, select with repeated options slows down significantly starting at 2000 options in Chrome and Internet Explorer / Edge.

get object from datalist ng-repeat angular

I got datalist such as below ,and color a color object with name and id properties.
<datalist id="opts">
<option ng-repeat="color in colors" value = "{{color.id}}">color.name</option>
</datalist>
My problem is that i want to run a function with the id and the name of the selected color. how can i access both of them without show the id on the view?
<button ng-click="someFunction(color.id,color.name)">button </button>
You should do it manually, as ng-options directive would be good option to go, but unfortunately it doesn't supported for datalist. To get selected value inside controller scope you need to add ng-model to datalist
Markup
<datalist id="opts" ng-model="selectedColor">
<option ng-repeat="color in colors" value = "{{color.id}}">color.name</option>
</datalist>
<button ng-click="someFunction(selectedColor)">button</button>
And then do filter on color collection inside controller someFunction
$scope.someFunction = function(){
var selected = $filter('filter')($scope.colors, {id: parseInt(selectedColor)}, true),
selectedColor;
if(selected){
selectedColor = selected[0];
}
}
Use Angular Expression to Bind {{color.name}} in option or use Value attribute
<option ng-repeat="color in colors" value = "{{color.id}}" ng-change="someFunction(color )">{{color.name}}</option>
You can also give a try to use ng-change in side the datalist
Example:
<datalist id="opts">
<option ng-repeat="color in colors" value = "{{color.id}}" ng-change="someFunction(color )">{{color.name}}</option>
</datalist>
Now With in the Function You can Access both the id and name...For this No need of submit button
$scope.someFunction = function(colorobj){
var colorid=colorobj.id;
var colorname=colorobj.name;
}
You can do as illustrated below.
Pass directly the object - 'color' and access the 'id', 'name', etc in the controller.
HTML:
<button ng-click="someFunction(color)">button </button>
JS:
$scope.someFunction = function (colorObj) {
// access colorObj.id, colorObj.name, etc.
}

Trigger filter only on click

I have a list of data, this data is filtered by a dropdown menu.
The problem is, i want the filtering to be triggered only on a button click, not on the dropdown change.
<select ng-model="annee" ng-options="annee.titre for annee in annees track by annee.id">
</select>
<input type="submit" name="submit" value="Filtrer">
<ul>
<li ng-repeat="x in accueils | filter:annee" >
{{x.titre}}
<div ng-bind-html="x.description | to_trusted"></div>
{{x.date}}
{{x.cout}} $
{{x.participants}} participants
</li>
</ul>
Here is a working example :
http://plnkr.co/edit/MbfrhdKfbTObybsQvxrR?p=preview
I want the filter to be triggered on clicking on the "filter" button
Is it possible ?
Thanks a lot!
Note that your filter code here doesn't match your Plunker; it's filter:{annee:annee.id} in the Plunker.
You want to decouple the ng-repeat from the ng-model. One way to do this is to filter based on a new property and update that property only when the Filter button is clicked.
In your HTML:
Add a <form> element and set ng-submit to call submit() when the Filter button is pressed:
<form ng-app="myApp" ng-controller="customersCtrl" ng-submit="submit()">
Change the ng-repeat filter to use a new property instead of the property used by the <select> element's ng-model:
<li ng-repeat="x in accueils | filter:{annee:currentAnnee.id}">
In your controller:
Create the new property initialized with an invalid id:
$scope.currentAnnee = {
"id": 0
};
Create a submit() function that sets the new property from the <select> element's ng-model:
$scope.submit = function() {
$scope.currentAnnee = $scope.annee;
};
See this Plunker for a complete example.
As pointed by #msmolens, there were some differences in your plunker and the code you posted here. Secondly, the two arrays that you have used, have nothing in common so for demonstration purposes i have changed the structure of the second array that will be used as filter.
To start with, decouple your Array filter from the model value of the select drop down.
<select ng-model="annee" ng-options="annee.date for annee in annees track by annee.id">
</select>
<input type="submit" name="submit" value="Filtrer" ng-click="filter()">
<ul>
<li ng-repeat="x in accueils | filter:filterExpr" >
{{x.titre}}
<div ng-bind-html="x.description | to_trusted"></div>
{{x.date}}
{{x.cout}} $
{{x.participants}} participants
</li>
</ul>
As visible in the code, we have a model variable for the filter expression in the ng-repeat.
We then initialize the filter expression with a blank value.
$scope.filterExpr = {"date" : ''};
There after, you just need to capture ng-click of the filter button and modify the variable being used as a filter.
$scope.filter = function() {
$scope.filterExpr = {"date" : $scope.annee.date};
};
You can find the updated plunker here.

Resources