Removing a value from an array and moving them to another Array - angularjs

I have a dropdown values from $scope.role from there I am able to select and remove the respective value from that dropdown and moving the values to $scope.multiRoles array . Which I am also displaying as tags .Which can be find in AddRole()
Now when I click close button in the tag, I am calling removeRoles() , where I am splicing the array which I am selected. But I need to splice them and move them back to $scope.role. Till removing value it works fine , but I am unable to move it back to $scope.role as well. I need atleast one tag should be remained, I can not delete all of them.
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($index)">Click to Add your Role</button>
</div>
</div>
<div ng-if="rolesAdded" class="col-sm-12 col-xs-12">
<span class="tag label tagStyle newStyling" alue="data" ng-repeat="data in multiRoles track by $index">
<span>{{data}}</span>
<a><i ng-click="removeSelection()"class="remove glyphicon glyphicon-remove-sign "></i></a>
</span>
</div>
JS:
$scope.AddRole = function(index) {
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);
$scope.model.role = $scope.role[0];
}
$scope.rolesAdded = true;
};
$scope.removeRoles = function(index) {
debugger;
if ($scope.multiRoles !== null) {
$scope.multiRoles.splice(index, 1);
}
};

In your html import data to your removeRoles(data) function:
<button ng-click="removeRoles(data)">
<i class="remove glyphicon glyphicon-remove-sign"></i>
</button>
In your controller:
$scope.removeSelection = function(data) {
$scope.multiRoles.splice($scope.multiRoles.indexOf(data), 1);
$scope.role.push(data);
$scope.rolesAdded = $scope.multiRoles.length === 0 ? false : true;
};
Code here. Hope this helps.

Related

Set already selected values in angular 1 dynamic select dropdown while ng-click throghing error - TypeError: selectize.setValue is not a function

I have a select dropdown with option values. And this select dropdown is dynamically displaying. I want to show the selected value of each dropdown while selecting/clicking each select dropdown.
My blade file is
<div class="accordion__item" data-ng-repeat="pref_favs in coachProfileCtrl.coach.child_pref_categories" id="#{{pref_favs.pref_categories.id}}">
<div data-ng-click="coachProfileCtrl.loadprofilecategoryactions($event);" data-id="#{{pref_favs.pref_categories.id}}" class="accordion__header">#{{pref_favs.pref_categories.title}}</div>
<div class="accordion__body_new">
<p >
<select targetfield="title" general-selectize-directive id="category_videos_selectize_#{{pref_favs.pref_categories.id}}" service="category_videos" name="category_videos" multiple="multiple" style="display: block;" data-ng-model="coachProfileCtrl.coach.category_videos">
<option value="" disabled selected>{{ trans('frontend::messages.select_action') }}</option>
</select>
<div class="save-button">
<button type="button" class="btn btn-warning" data-ng-click="coachProfileCtrl.saveprofilecategoryactions();">Save Actions</button>
</div>
</p>
</div>
</div>
</div>
And my click action is like
this.coach.category_id = $($event.target).attr('data-id');
angular.forEach($scope.categories_actions_lists, function(value, key) {
if(key == $($event.target).attr('data-id') ) {
var $select = $("#category_videos_selectize_" + key ).selectize();
var selectize = $select[0].selectize;
selectize.setValue(value);
}
});
and am getting errors like
TypeError: selectize.setValue is not a function
Any help!
Yes, finally I got the answer!
if(key == $($event.target).attr('data-id') ) {
$("#category_videos_selectize_" + key)[0].selectize.setValue(value);
}

Two way binding in *ngFor on Array of elements(non-object)

I have a simple array tags = []; and I'm pushing blank element on addNew() using this.tags.push("");. It creates blank element in that array.
Now, I'm using this array to add multiple items to be added from the input
<div class="row tagEntry" *ngFor="let tag of tags, let i = index">
<div class="col-md-10">
<input type="text" name="tag-{{i}}" placeholder="Tag Name" [(ngModel)]="tag" class="form-control">
</div>
<div class="col-md-2">
<button class="btn btn-block btn-danger" (click)="removeTag(i)"><i class="fa fa-trash"></i></button>
</div>
</div>
My TS file:
todoDesc: string = '';
tags = [];
ngOnInit() {
}
addTag () {
this.tags.push("");
console.log(this.tags)
}
removeTag (index) {
this.tags.splice(index, 1);
}
addTodo () {
console.log(this.todoDesc, this.tags)
}
Issue here is, it is not binding the input and array two way. When I log the array after updating inputs, the array displays items with all blank value.
How to two way bind the array of elements in Angular 5 using *ngFor?
The issue is with Array whose changes are not being detected through reference. You can make the following changes -
html
<div class="row tagEntry" *ngFor="let tag of tags; let i = index; trackBy:trackIndex">
<div class="col-md-10">
<input type="text" placeholder="Tag Name" [(ngModel)]="tags[i]" class="form-control">
</div>
<div class="col-md-2">
<button class="btn btn-block btn-danger" (click)="removeTag(i)"><i class="fa fa-trash"></i></button>
</div>
</div>
ts
Add the following function in ts file. This function is very important otherwise the array will re-build the complete UI on any change and you will loose the focus from the elememt.
trackIndex(index,item){
return index;
}
Here is the working copy - https://stackblitz.com/edit/angular-pzdw6s

AngularJS - Enable and disable button

I have a condition and it is only on selecting an image among the optional images the next button needs to get enabled and also next should not get enabled on last outer select.
The problem here is on selecting the first image, the button is getting enabled and the scope is assigning the value to false and it is not getting true for the second iteration of images. How can I fix this issue?
<div class="col-xs-6 col-md-10 col-lg-7">
<div ng-repeat="outer in outers track by $index">
<div ng-if="outer_index== $index">
<div ng-bind="::outer.label"></div>
<ul class="list-group">
<li class="cursorPointer" ng-repeat="inner in outer.inners | orderBy: 'id'" ng-class="{'selected': getSelectedClass($parent.$index, $index)}" class="deselected">
<div class="col-xs-6">
<div class="img">
<img ng-src="data:image/png;base64,{{inner.base64Icon}}" alt="{{inner.description}}" title="{{inner.description}}"
ng-click="process()">
<div class="desc" ng-bind="inner.description"></div></div>
</div>
</li>
</ul>
</div>
</div>
</div>
<div><button type="button" class="btn btn-info" ng-disabled="outer_index == outers.length -1 || disableNext" ng-click="getNext()">Next</button></div>
In JS code, to activate the button only if,
$scope.disableNext=true;
$scope.process = function() {
$scope.disableNext=false;
}
$scope.getNext = function (){
$scope.outer_index = $scope.outer_index + 1;
$scope.datas = $scope.outers[$scope.outer_index];
}
NOTE: I tried
ng-click="process();disableNext=false;" for this condition won't work within ng-repeat.
Just set the disableNext to true after selecting next and it works!
$scope.getNext = function() {
$scope.disableNext=true;
$scope.outer_index = $scope.outer_index + 1;
$scope.datas = $scope.outers[$scope.outer_index];
}

ngModel checkbox not shown as selected

I'm having some trouble getting a checkbox to display the correct state (checked/unchecked) of my model. I have the following in my controller:
app.controller('PhotosCtrl', ['$scope', function($scope) {
$scope.form = {};
$scope.editPhotos = {
token: $scope.token,
idArray: $scope.idArray
};
}]);
My form looks like this:
<form accept-charset="UTF-8" name="editPhotosForm" ng-submit="submit(editPhotos);" multipart="true" novalidate>
<input name="utf8" type="hidden" value="✓">
<input name="authenticity_token" type="hidden" ng-model="editPhotos.token" ng-init="editPhotos.token='<%= form_authenticity_token %>'">
<div class="results-label"><b>{{total_count}}</b> <span ng-if="total_count == 1">Photo</span><span ng-if="total_count != 1">Photos</span> Found</div>
<div>
<div class="col">
<a ng-repeat="r in results" class="card result-link">
<div class="content result">
<div class="caption">
<input type="checkbox" ng-model="idArray[r.id]">
</div>
<div class="image-container" ng-style="{'background-image': 'url(' + r.image_url + ')'}">
</div>
</div>
</a>
</div>
</div>
</form>
On my repeater element, I call ng-init="idArray[r.id] = 'false'" to initialize a key r.id = 'false' for each item in r. I don't know if I need to do this or not. I've tried the code without it and it makes no difference. I've also tried using ng-value-true and ng-value-false but those don't seem to be working for me.
Most of the other posts I've seen on this issue deal with simple variables (e.g. $scope.someVar = true rather than more complex structures like a hash.
Here is the structure of idArray:
$scope.idArray = {1290: "false", 1291: "true", 1292: "true", 1293: "false", 1294: "false", 1414: "false"};
This is generated by the ng-init in my repeater, since the ids of the photos can't be known beforehand.
Here is what results looks like:
{
id: 1290,
company_id: null,
image_url: "http://s3.amazonaws.com/mybucket/photos/images/000/001/290/original/214.JPG?1432217895"
}
Doing the following
ng-init="idArray[r.id] = 'false'"
You're assigning the string value 'false' into your object.
Can't you deal with that inside your controller?
$scope.idArray = {};
for (var i = 0; i < $scope.results.length; ++i){
$scope.idArray[$scope.results[i].id] = (i%2 == 0);
}
And removing the ng-init="" (which is, according to Angular doc, a bad practice https://docs.angularjs.org/api/ng/directive/ngInit ).
Another thing was the anchor element that was wrapping the checkbox element. This lead to the click event that was not triggered on the checkbox, but only on the anchor.
<div class="col">
<div ng-repeat="r in results" class="card result-link">
<div class="content result">
<div class="caption">
<input type="checkbox" ng-model="idArray[r.id]">
</div>
<div class="image-container" ng-style="{'background-image': 'url(' + r.image_url + ')'}">
</div>
</div>
</div>
</div>
fiddle :
http://jsfiddle.net/patxy/wak7pwwp/

Angularjs autocomplete directive in 2 places in same dom

Hi,
I am building an autocomplete directive and I need it at two places in the same form. The autocomplete feature works fine but it shows the same directive at both the places. I have attached a image with this question, referring the Image even if I type in teh to colum the country autocomplete is also activated, how to I bind it to only the element where user is interacting ?
following is my code for the directive
angular.module('xyz').directive('autoComplete',['$rootScope',function($rootScope){
return {
restrict:'AE',
transclude: true,
replace: true,
scope:{
selectedTags:'=model',
userdata:'=',
name:'#'
},
templateUrl: function(elem,attr){ return 'views/rad/layout/autocomplete.html' },
link:function(scope,elem,attrs){
scope.suggestions=[];
scope.selectedTags=[];
scope.selectedIndex=-1; //currently selected suggestion index
scope.search=function(){
var newSuggestions = [];
// if(attrs.userdata.indexOf(scope.searchText)===-1){
// //dataUser.unshift(scope.searchText);
// }
for(var i=0; i < scope.userdata.length;i++)
{
if(dataUser[i].toLowerCase().indexOf(scope.searchText.toLowerCase()) !== -1){
newSuggestions.push(dataUser[i]);
}
}
scope.suggestions = newSuggestions;
scope.selectedIndex = -1;
}
scope.checkKeyDown=function(event){
console.log(event.keyCode);
if(event.keyCode===40){//down key, increment selectedIndex
event.preventDefault();
if(scope.selectedIndex+1 !== scope.suggestions.length){
scope.selectedIndex++;
}
}
else if(event.keyCode===38){ //up key, decrement selectedIndex
event.preventDefault();
if(scope.selectedIndex-1 !== -1){
scope.selectedIndex--;
}
}
else if(event.keyCode===13){ //enter pressed
scope.addToSelectedTags(scope.selectedIndex);
}
}
scope.addToSelectedTags=function(index){
if(scope.selectedTags.indexOf(scope.suggestions[index])===-1){
scope.selectedTags.push(scope.suggestions[index]);
scope.searchText='';
scope.suggestions=[];
}
}
scope.$watch('selectedIndex',function(val){
if(val!==-1) {
scope.searchText = scope.suggestions[scope.selectedIndex];
}
});
scope.removeTag=function(index){
scope.selectedTags.splice(index,1);
}
}
}
}])
following is the auto complete template
<div class="tags-wrapper">
<div id="tagsList" class="tags-cloud">
<div class="suggestionListing">
<div ng-repeat="selectedTag in selectedTags track by $index" class="tag">
<span class="tagName">{{selectedTag}}</span>
<span> <b ng-click="removeTag($index)" class="fa fa-times cross"></b></span>
</div>
</div>
<div class="input-group">
<input type="text" name="{{inputname}}"placeholder="" aria-describedby="basic-addon2" id="searchInput" class="form-control no-border" ng-model="searchText" ng-keydown="checkKeyDown($event)" class="form-control" ng-model="searchText" ng-change="search()"/>
<div class="suggestions-list">
<div ng-repeat="suggestion in suggestions track by $index" class="blockSpan" ng-click="addToSelectedTags($index)" ng-mouseover="$parent.selectedIndex=$index" ng-class="{active : selectedIndex===$index}">
<div class="userAvatar">
<i class="fa fa-user"></i>
</div>
<div class="userInfo">
{{suggestion}}
</div>
<br clear="all" />
</div>
</div>
</div>
</div>

Resources