How to remove item from an array - angularjs

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.

Related

Angularjs binding updates all selects in ng-repeat

When I'm using ng-model inside of ng-repeat it updates all ng-models inside that repeat loop. If I remove datatype and directly set to myCtrl.data[$index] it works fine.
Any suggestions?
template:
<div ng-repeat="i in myCtrl.data track by $index">
<div>
<div>
<select
ng-model="myCtrl.data[$index].datatype"
ng-options="item.value as item.label for item in myCtrl.detailTypes track by item.label"
>
<option value="" disabled selected>
select an option
</option>
</select>
</div>
</div>
</div>
controller:
self.detailTypes = [
{label: 'KEY_1', value: 'VAL_1'},
{label: 'KEY_2', value: 'VAL_2'},
];
self.data = new Array(2).fill({dataType: null});
When I select KEY_1 for first select, it changes object to [{dataType: 'VAL_1'}, {dataType: 'VAL_1'}]
Ok so this is happening because you are populating your self.data with Array.fill which when used with objects, passes by reference not value.
If you change declaration of your self.data to this
self.data = [];
self.data.push({dataType:null},{dataType:null});
it will work.

Add Select option dynamically in Angularjs

I have a select list. I am populating the list using ViewBag.But for few cases it is required to add dynamic items to the selected list.
I am able to add those items but while those values are fetched it returns null for those newly added items.No problem with getting values for other items added using 'ViewBag'.
HTML:
<select ng-model="JobNo" id="JobNo" name="JobNo" class="myClass" style="width:100%;">
<option ng-repeat="item in JobList.Data" value="{{item.ProjectCode}}">{{item.ProjectDescription}}</option>
</select>
<input type="button" value="Save Data" ng-click="SaveData()">
Controller:
$scope.JobList = #Html.Raw(Json.Encode(ViewBag.ProjectCode))
//Added new item here
$compile(angular.element($("#JobNo option")).eq(0).after($compile('<option value="ALL"> -- ALL -- </option>')($scope)));
$scope.SaveData=function () {
alert($scope.JobNo); // it's show 'null' when I select "--ALL--" but no problem in other cases
}
In Controller add new item in Joblist.Data array at first index, instead of DOM injection.
$scope.JobList = #Html.Raw(Json.Encode(ViewBag.ProjectCode))
//Added new item here
$scope.JobList.Data.unshift({
ProjectCode: 'ALL',
ProjectDescription: ' -- ALL -- '
})
or
you can try add an option in html and remove option injection from controller, here is the codes,
html
<select ng-model="JobNo" id="JobNo" name="JobNo" class="myClass" style="width:100%;">
<option value="ALL"> -- ALL -- </option>
<option ng-repeat="item in JobList.Data" value="{{item.ProjectCode}}">{{item.ProjectDescription}}</option>
</select>
<input type="button" value="Save Data" ng-click="SaveData()">
controller
$scope.JobList = #Html.Raw(Json.Encode(ViewBag.ProjectCode))
$scope.SaveData=function () {
alert($scope.JobNo);
}
Try this:
<select ng-options="listname for refvar in displayname track by value" ng-model="selected value's variable"></select>

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'}
]
});

Angular : pass mutliple values to the controller

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>

$scope.$digest() doesn't populate select2 drop down list

I have 2 drop down lists using ui-select2
<label class="control-label" for="MakeSelect">Make </label>
<select class="form-control col-md-2" id="MakeSelect" name="make" ui-select2
ng-model="carDetails.make">
<option ng-if="!carDetails.make" value="">[SELECT]</option>
<option ng-repeat="make in makes" value="{{ make }}">{{ make}}</option>
</select>
</div>
<div class="col-md-5">
<label class="control-label" for="ModelSelect">Model </label>
<select class="form-control col-md-2" id="ModelSelect" name="make" ui-select2
ng-model="carDetails.model">
<option ng-repeat="model in models" value="{{ model }}">{{ make}}</option>
</select>
After I choose a value in the drop down list "Makes" I am activating a watch that inside it I load the content of "Models" Dropdown lists.
Then, In order to refresh the drop down lists content in the GUI I call $scope.$digest() :
$scope.$watch('carDetails.make', function (make) {
console.log('selected make is: ' + make);
if (make == "") {
return;
}
Parse.Cloud.run('getCarModels', {'Make': make}, {
success: function (results) {
$scope.parseModels = results.resultSet;
$scope.models = results.distinctModels;
$scope.$digest();
},
error: function () {
console.log("Error: Failed to load models");
console.log(Parse.Error);
}
});
The problem is that with $digest the selected value of the first drop down list is becoming null and without it just doesn't refresh the view.
Any suggestions please?
They're both pointing to the same scope model, carDetails.make. So, of course, the first will become null, because the second drop down list sets carDetails.make to null. Also, I don't think you need to use digest, although, you should be using $scope.$apply. But, angularjs should run the digest anyway.

Resources