Angular generating multiple ng-repeats - javascript

In my angular application (angular 1.4.9) I have a problem, where multiple ng-repeats are generated when I do this:
HTML:
<div class="form-group col-md-3">
<input ng-model="main.startLocation" ng-change="main.getAddressSuggestions(main.startLocation, 'startLocation')" type="text" class="form-control input-lg" placeholder="fx. Aarhus" tabindex=1 name="country" [![enter image description here][1]][1] />
<label>or select a location from list:</label>
<div ng-repeat="suggestion in main.startLocationSuggestions">
<span>{{suggestion}}</span>
</div>
</div>
controller.js
getAddressSuggestions(address, inputName) {
if (inputName === "startLocation") {
/* var tmpArray = data;
for(var item of tmpArray)
this.startLocationSuggestions = data;*/
this.startLocationSuggestions = ['dada', 'daa'];
}
}
But the generated HTML in the dom is:
Why does angular repeat the ng-repeats?

If you don't want to repeat parent element, here is html:
<div >
<span ng-repeat="suggestion in startLocationSuggestions">{{suggestion}}</span>
</div>
Output will be as:
<div>
<!-- ngRepeat: suggestion in startLocationSuggestions -->
<span ng-repeat="suggestion in startLocationSuggestions" class="ng-scope ng-binding">dada</span>
<span ng-repeat="suggestion in startLocationSuggestions" class="ng-scope ng-binding">daa</span>
</div>
This is how ngRepeat works.

this is basically how the ng-repeat works!
at the start it writes a comment like:
<!-- ngRepeat: x in items -->
then for every element that's been created with ng-repeat, after creating it (WITH the ng-repeat attribite inside), writes another comment:
<!-- end ngRepeat: x in items -->

Because it just takes your template as is (div ng-repeate lalala), clones it N times, fills with data and put into DOM.

Related

How to remove and add dropdown values based on the condition selected by another dropdown in angular?

My requirement:
I have to create a form row that has two select dropdowns and add and delete button at last
1. the first dropdown will have a list of values for ed.. ['one', 'two', 'three','four']
2. the second dropdown will have the condition ['and','or']
let say the first row of the form value selected like ['one'] ['and'] then clicking on the add button then the second row will create. here first dropdown should not show the 'one' value because the condition is 'and'. if user select or then it should all the values. similary for all the rows i have to create logic in angular.
HTML Code:
<div class="state-filter-conditions-grid subs-model-sec filter-grid" *ngFor="let filterCondition of filters; index as i">
<!-- OUTPUT PROPERTY -->
<ng-container *ngTemplateOutlet="filterView == 'subscription'? attrs: map; context: { index: i }"></ng-container>
<!-- CONNECTOR CONDITION -->
<div class="dt-attr valueCondition ctrl-condition minimal">
<div class="abs-cheveron select-box-cheveron">
<select class="state-select" [(ngModel)]="filters[i].op">
<option *ngFor="let val of op" [value]="val">{{val}}</option>
</select>
</div>
</div>
<!-- INPUT -->
<ng-container *ngTemplateOutlet="filterView != 'subscription'? attrs: map; context: { index: i }"></ng-container>
<!-- SELECT -->
<div class="dt-attr icons center-align">
<select class="ctrl-condition" *ngIf="!(i==filters.length-1)" [(ngModel)]="filters[i].logop" (change)="operatorChange(filters[i])">
<option *ngFor="let val of logop" [value]="val">{{val}}</option>
</select>
</div>
<!-- ICONS -->
<div class="dt-attr icons center-align">
<button *ngIf="i==filters.length-1" class="add-btn" (click)="addStateConditionRow()"><i
class="fa fa-sm fa-plus add-icon" aria-hidden="true"></i></button>
<button *ngIf="i>0" class="delete-btn" (click)="deleteStateConditionRow(i)"><i
class="fa fa-sm fa-trash delete-icon"></i></button>
</div>
</div>
<ng-template #attrs let-i="index">
<div class="dt-attr ">
<ng-container *ngIf="!dataProps">
<input class="ctrl-attr" type="text" [(ngModel)]="filters[i].value">
</ng-container>
<ng-container *ngIf="dataProps">
<select class="value-select" [(ngModel)]="filters[i].value">
<option *ngFor="let data of dataProps" [value]="data.attrId">{{data.attrName}}</option>
</select>
</ng-container>
</div>
</ng-template>
<ng-template #map let-i="index">
<div class="dt-attr ctrl-condition minimal">
<input class="ctrl-attr" type="text" clickOutside (clickOutside)="closeAccordion($event)" (click)="openAccordion($event)" [(ngModel)]="filters[i].attribute">
<div *ngIf="showAccordion" class="state-filter-accordion" style="position: absolute;
top: 105%;
width: 100%;z-index:1">
<app-common-accordion-mapping [filterInputRef]="filterInputRef" [inputAttributes]='inputAttributes' ></app-common-accordion-mapping>
</div>
</div>
</ng-template>
can you guys help me to achieve this.
Thanks in advance.
I think what you are looking for is to dynamically populate dropdown based on a particular logic. This stackoverflow answer covers that for AngularJS and a stackoverflow question + blog for Angular 8 . However I cannot help you with the business logic itself as it is not clear to me.

use ngFor loop in Angular 6 to dynamically create array of input elements and add dynamical validation based on template reference variables

I would like to create dynamically 3 input tags in Angular 6 to not copy/paste html code because that input elements have similar html and functionality.
For this purpose I created an array "reusableItems" inside component and initialize it :
let numberOfInputElements = 3;
for (let i = 0; i < numberOfInputElements; i++) {
this.reusableItems.push({
answer: 'Answer ' + (i +1),
passwordRecoveryAnswer: this.user['passwordRecoveryAnswer' + (i + 1)]
});
}
Then I put code inside my html :
<div *ngFor="let item of dropDownDataManagerService.reusableItems" >
<li class="col-xs-12 pl-lg pr0 pv-sm bd1-bottom">
<div class="col-xs-4 ph0 pt"> {{item.answerTitle}}</div>
<div class="col-xs-8">
<input type="text" name={{item.answer}} ref-{{item.answer}}="ngModel" class="col-sm-12 k-textbox ph0"
[(ngModel)]=item.passwordRecoveryAnswer
[pattern]="[a-z]"
required autocomplete="off"/>
</div>
</li>
</div>
It seems works fine but then I need to add error messages when these fields will be empty and not match to pattern. Something like :
<div *ngIf="__{{item.answer}}__.errors?.required ">
{{'Please provide an answer' | translate}}
</div>
<div *ngIf="__{{item.answer}}__.errors?.pattern">
{{'Pattern is not match'}}
</div>
I don't know what should i put inside ngIf condition.
How can I do it if my template reference variables are comes from array?
Is anyone have ideas?
Thanks
Angular creates unique template reference variable for each embedded template so that you can use the same template reference variable name inside ngFor loop:
<div *ngFor="let item of reusableItems">
<li class="col-xs-12 pl-lg pr0 pv-sm bd1-bottom">
<div class="col-xs-4 ph0 pt"> {{item.answerTitle}}</div>
<div class="col-xs-8">
<input type="text" name={{item.answer}} ref-answer="ngModel" class="col-sm-12 k-textbox ph0" [(ngModel)]="item.passwordRecoveryAnswer"
[pattern]="'[a-z]'" required autocomplete="off" />
<div *ngIf="answer.errors?.required">
{{'Please provide an answer'}}
</div>
<div *ngIf="answer.errors?.pattern">
{{'Pattern is not match'}}
</div>
</div>
</li>
</div>
In the code above I use the same name for each input in array
ref-answer="ngModel" // or you can also use #answer="ngModel

how to delete object in an array with filter used? AngularJS

I have something like an input to add items into either column 1 or column 2 and each time adding the items, the column will show up what is added right away with an 'X' beside it so if you want to delete the item just click on 'X'. At first I wasn't thinking much so I used an easy way to remove the HTML but then I realized, that's just removing the HTML (There's also a search input if I type something into search and clear the search, all items will show again). This is when I realized just removing the HTML is a mistake that I need to remove the object too but how can I make it so it'll delete the right object in the array?
My angular script
angular.module("addItemApp", [])
.controller("toDoCtrl", function ($scope) {
$scope.items = [];
$scope.addItem = function (item) {
console.log(item);
$scope.items.push(angular.copy(item));
console.log($scope.items);
};
$scope.remove = function (item) {
var index = $scope.items.indexOf(item);
$scope.items.splice(index, 1);
}
});
my html
<div class="row">
<div class="col-xs-6 col-sm-4 left-column">
<div class="input-item">
<input type="text" placeholder="Enter Item" ng-model="item.name" class="enter-item">
<select class="column-select" ng-model="item.pos">
<option value="default" selected>Choose Column</option>
<option value="column1">Column 1</option>
<option value="column2">Column 2</option>
</select>
<button class="add-button" type="button" ng-click="addItem(item)">Add Item</button>
</div>
<div class="search-item">
<label for="search">Search An Item</label>
<div class="search-input">
<input ng-model="query" type="text" placeholder="Search" id="search"><span class="fa fa-search icon-search"></span>
</div>
</div>
</div>
<div class="col-xs-6 col-sm-4">
<h3 class="column-header column1">
Column 1
</h3>
<ul ng-repeat="item in items | filter:{ pos: 'column1' } | filter:query">
<li>{{item.name}}
<button remove-on-click ng-click="remove()" class="remove-button fa fa-times"></button>
</li>
</ul>
</div>
<!-- Optional: clear the XS cols if their content doesn't match in height -->
<div class="clearfix visible-xs-block"></div>
<div class="col-xs-6 col-sm-4">
<h3 class="column-header column2">
Column 2
</h3>
<ul ng-repeat="item in items | filter:{ pos: 'column2' } | filter:query">
<li>{{item.name}}
<button remove-on-click ng-click="remove()" class="remove-button fa fa-times"></button>
</li>
</ul>
</div>
</div>
Thanks in advance everyone.
you can do it in two ways -
1
$scope.remove = function(item) {
var index = $scope.items.indexOf(item);
$scope.items.splice(index, 1);
}
<button ng-click="remove(item)"></button>
2
$scope.remove = function(index) {
$scope.items.splice(index, 1);
}
<button ng-click="remove($index)"></button>
Please note that, when filter is applied, the $index may not be the one you should use to remove, better go with first approach. I have given example of $index for your reference.
<button ng-click="remove(item)"></button>
should work, since item is defined earlier in the ng-repeat and you already have a remove function defined on your $scope.

How to add data and data flow in Ionic App using angular js

In AngularJS I want to create a birthday card list where I select my friends list from my JSON file and fill date of my selected friends.
I show my friends list in my index.html as
<!-- immutable scripts added -->
<script src="js/immutable.min.js"></script>
<ion-content class="has-subheader" >
<!-- card list declaration -->
<ul class="card">
<!-- checkBox Declaration and filtering by search box -->
<li class="item item-thumbnale-left" ng-repeat="item in items | filter:query">
<!-- show friends list in cards -->
<input type="text" ng-model ="friend.Name"
ng-init = "friend.Name = item.Name" readonly/>
<!-- take a input field for taking friend b'day date -->
<div class="item item-input-inset">
<!-- click a checkbox for add friend -->
<label class="checkbox">
<input type="checkbox" ng-click ="saveOrDelBirthday(friend)"
ng-show = "friend.Date" ng-model = "friend.check"/>
</label>
<label class="item-input-wrapper">
<input type="date" placeholder="Enter Date"
ng-model = "friend.Date" />
</label>
</div>
</li>
</ul>
</ion-content>
when i click a show button then a new list.html shows all selected friends list with their birthday but
My selected friend list is not showing the list in
list.html file as
<ion-content>
<ul class="card">
<li class="item" ng-repeat="(key,value) in information">
<div style="float: left">{{ key }}</div>
<div style="float: center">{{ value }}</div>
</li>
</ul>
<label class="item">
// this is for sending mail to me from my app
<button class="button button-positive" type="submit" ng-click = "sendMailMe()" >Confirm</button>
</label>
I use immutable data structure for storing data with key value pair in immutable.Map({});
I don't know where i'm wrong.
//my controller contain this method
$scope.information = {}; //storing data from map
var friendMap = Immutable.Map({}); //declaring Map for inserting data in key value pair
$scope.friendMap1;
//this section decide which operation perform
$scope.saveOrDelBirthday = function(friend){
console.log(friend.check);
if(friend.check){
friendMap1 = friendMap.set(friend.Name,friend.Date); //insert friend information
}
else{
friendMap1 = friendMap.delete(friend.Name); //delete friend information
}
information = friendMap1.toObject();
console.log(information);
};
It looks like $scope.information expected by the ng-repeat directive isn't being defined in your controller or is returning an empty list/object.

How to click on multiple elements having same class name in protractor angular?

First element html code:
<div class="block ng-scope" ng-repeat="skills in data.primary_skills">
<div class="block skillsLineItem" ng-class="{manditorySkillsLineItem:skills.mandatory, skillsLineItem:!skills.mandatory}">
<label title="Testing" class="skill-name col-xs-5 text-overflow-ellipsis ng-binding" ng-click="toggleMandatory(skills)">
<!-- ngIf: skills.mandatory -->
<!-- ngIf: skills.userdefined -->
Testing
</label>
Second element Html code
<label title="Test Scripts" class="skill-name col-xs-5 text-overflow-ellipsis ng-binding" ng-click="toggleMandatory(skills)">
<!-- ngIf: skills.mandatory -->
<!-- ngIf: skills.userdefined -->
Test Scripts
</label>
In our application multiple elements having same class name and ng-click values so how can i click on multiple elements using same class or ng-click values. I have to click on both elements so please help me.
You can find all of them and use each():
element.all(by.css("label[ng-click*=toggleMandatory]")).each(function (label) {
label.click();
});
You can use filter() to filter out only necessary elements:
element.all(by.css("label[ng-click*=toggleMandatory]")).filter(function (label, index) {
return index <= 5;
}).each(function (label) {
label.click();
});

Categories

Resources