ng-if for comparing dynamic json values - html

I am new to AngularJs
I have two JSON objects one is "products" and and another is "users"
I have two ng-repeat one is for product display and inside that to get user name of product i have another loop.
In the inner loop I need to check userId from product JSON and compare it with userId in User object and if matches display it in P tag.
My code is as follows:
<div class="col-md-4" ng-repeat="(key,value) in products" style="padding-top: 1.4%; padding-bottom: 1.4%;" >
<img style="height:300px;width:350px" ng-src="{{products[key].image}}"></img>
<div ng-repeat="(userkey,value) in User">
<p ng-if="User[userkey].userId == products[key].user">{{{User[userkey].name}}</p>
</div>
</div>
I have tried like this but it is displaying all users in p tag.
Can anyone please help with this

You could do that with filter:
oneUser in User | filter: {userId:product.user}:true
fiddle
EDIT
The way you should do that is with filters, you could use ng-show/ng-hide but you are still rendering that item as a comment, while with filter it will not. So use this for large data.

<div class="col-md-4" ng-repeat="product in products" style="padding-top: 1.4%; padding-bottom: 1.4%;" >
<img style="height:300px;width:350px" ng-src="{{product.image}}"></img>
<div ng-repeat="(oneUser in User">
<p ng-show="oneUser.userId == product.user">{{{oneUser.name}}</p>
</div>
</div>

This is what worked for me -
<div ng-repeat="p in products">
<div ng-repeat="u in users">
<p ng-show="u.userId == p.user">
{{u.name}}
</p>
</div>
</div>
Fiddle - http://jsfiddle.net/halirgb/Lvc0u55v/

Related

Problem with displaying array length correctly

In an Angular project, I want to loop through filterLifePolicies array because I want to pass via URI the LobDsc property.
The problem is that I also want to output as a number the length of the array but because I loop through each element if the array contains e.g.
3 objects, 3 cards are displayed...I only want one card with the number 3 (array length).
HTML:
<div class="card" *ngFor="let policy of filterLifePolicies">
<a [routerLink]= "['/contracts', policy.LobDsc]"
routerLinkActive="active" class="noLinksDecoration">
<div class="card-body text-center">
<img src="../../assets/images/Component62_1.svg">
<p class="policyTitle">Ζωή & Υγεία</p>
<p class="counter">{{countLife}}</p>
</div>
</a>
</div>
Part of Typescript:
getCustomerPolicies () {
this.http.get<any>('http://localhost:8080/o/mye/pol').subscribe({
next: res => {
this.filterLifePolicies = res.Life.Policies;
console.debug(this.filterLifePolicies);
this.countLife = this.filterLifePolicies.length;
You can do the following, considering countLife variable is assigned the required value.
<div class="card">
<ng-container *ngFor="let policy of filterLifePolicies; index as i">
<a *ngIf="i < 1" [routerLink]="['/contracts', policy.LobDsc]" routerLinkActive="active" class="noLinksDecoration">
<div class="card-body text-center">
<img src="../../assets/images/Component62_1.svg">
<p class="policyTitle">Ζωή & Υγεία</p>
</div>
</a>
</ng-container>
<p class="counter">{{countLife}}</p>
</div>
In the above code snippet, ng-container is being used to iterate through filterLifePolicies in order to access LobDsc value. Since the iteration should not create duplicate HTML div elements with CSS class card-body, an additional check via ngIf is being used to check the index value, such that it should be always lesser than 1.
Although if the LobDsc value is the same for all the values of filterLifePolicies, the recommended approach would be to fetch its value via the dot notation and store it in a variable that can be later binded directly to your template during runtime.

PrimeNg - Toggle div inline inside ng-template loop

I'm working with PrimeNg picklist and here is what i have:
The focus is on the first row, don't mind the other rows not having the radio button (it's uncompleted testdata).
What i'm trying to achieve is that when you click on the first option 'Good:Stock', the little dropdown to the right with A1 appears. When you select 'Bad', it disappears.
The problem now is that when i select 'Good' for one item, the dropdown will appear for every record in the loop.
I want it to appear only for the item where i selected the radiobutton.
All help is welcome! Ask away if you need more code but i don't think the .ts file matters for now.
Here is what the code looks like:
<label for="productGroup">Select product</label>
<div class="form-group" id="productGroup">
<div class="row">
<div class="col">
<p-pickList [source]="products"
(onMoveToTarget)="onMoveToTarget()"
[target]="selectedProducts" sourceHeader="Available" targetHeader="Selected"
[responsive]="true" filterBy="description,productNumber"
dragdrop="true" dragdropScope="products" [showTargetControls]="false" [showSourceControls]="false"
sourceFilterPlaceholder="Search product in Available"
targetFilterPlaceholder="Search product in Selected"
[sourceStyle]="{'height':'33vh'}" [targetStyle]="{'height':'33vh'}">
<ng-template let-product pTemplate="item">
<div id="product" class="row ui-helper-clearfix">
<div class="col-1 padding-0 brighten">
<img (mouseover)="getProductImage(product)"
[escape]="false"
pTooltip='<img style="max-height: 100%; max-width: 100%" src="{{base64String}}">'
tooltipPosition="right"
src="assets/eye-icon.png" style="max-width: 100%; width: 80%;">
</div>
<div class="col-4">
<div class="row">{{product.description}}</div>
<br>
<div class="row">{{product.productNumber}}</div>
</div>
<div class="col-4" *ngIf="inbound && product.goodLabel && product.badLabelInWarranty &&!hqAdmin&&!carStock">
<div class="row">
<p-radioButton (onClick)="toggleProjects(true, product.id)" name="{{product.productNumber}}"
label="Good: {{product.goodLabel.name}}"
[value]="product.goodLabel" [(ngModel)]="product.quality">
</p-radioButton>
<p-radioButton name="{{product.productNumber}}"
label="Bad: {{product.badLabelInWarranty.name}}/{{product.badLabelOutOfWarranty.name}}"
[value]="product.badLabelInWarranty" [(ngModel)]="product.quality"
(onClick)="toggleProjects(false, product.id)">
</p-radioButton>
</div>
</div>
<div class="col-2 nopadding" *ngIf="goodSelected">
<p-dropdown id="dropdownInput"
[autoWidth]="false"
[options]="projectLabelSelectItems">
</p-dropdown>
</div>
</ng-template>
</p-pickList>
</div>
</div>
</div>
What is happening in you case suppose lets take an example you have 10 rows and your are maintaining one single variable for all row so what happen when the value of that flag become true or false drop-down from all the rows will show or hide.
So what is suggest in the collection take one property extra for this drop-down column.
<div class="col-2 nopadding" *ngIf="goodSelected">
<p-dropdown id="dropdownInput"
[autoWidth]="false"
[options]="projectLabelSelectItems">
</p-dropdown>
</div>
Here goodSelected is single variable insted of add one vriable in property
<div class="col-2 nopadding" *ngIf="product.goodSelected">
<p-dropdown id="dropdownInput"
[autoWidth]="false"
[options]="projectLabelSelectItems">
</p-dropdown>
</div>
And on toggle make goodSelected selected value true or false of selected row only.

Add class with [ngClass] depending on local html condition

I have used [ngClass] in the past, applying classes depending on the Boolean value of a variable held in the javascript/typescript before. However I am wondering if it is possible to apply it based on a local HTML boolean value or not?
ie.
<div class="card" *ngFor="let item of data" #panel ngClass="{expanded: isExpanded}">
<div class="header">
<div class="itemName">Text</div>
<div class="itemDir">Some more text</div>
<mat-icon *ngIf="!panel.isExpanded" (click)="panel.isExpanded=true">edit</mat-icon>
<mat-icon *ngIf="panel.isExpanded" (click)="panel.isExpanded=false">cancel</mat-icon>
</div>
</div>
Here, I am displaying one of two icons, depending on the local isExpanded variable defined within the HTML and not the backend.
I am wanting to apply a class based on this value... is it possible?
Here is what I am working on
use like [class.expanded]="isExpanded". binding to class.expanded trumps the class attribute
<div class="card" *ngFor="let item of data" #panel [class.expanded]="panel.isExpanded" [class.notExpanded]="!panel.isExpanded">
you can use *ngIf="true as isExpanded" to make variable on the template
<div class="card" *ngFor="let item of [1,2,3,4];" >
<div class="header" *ngIf="true as isExpanded" ngClass="{expanded: !isExpanded}">
<div class="itemName">Text</div>
<div class="itemDir">Some more text</div>
<div *ngIf="isExpanded" (click)="isExpanded=!isExpanded">edit</div>
<div *ngIf="!isExpanded" (click)="isExpanded=!isExpanded">cancel</div>
</div>
</div>
stackblitz demo 👍👍
<div class="card" *ngFor="let item of data" #panel ngClass="{expanded: isExpanded}">
<div class="header">
<div class="itemName">{{item.name}}</div>
<div class="itemDir">{{item.directory}}</div>
<mat-icon *ngIf="!isExpanded;else other_content" (click)="isExpanded=true">edit</mat-icon>
<ng-template #other_content>Other Icon goes here</ng-template>
</div>
You can refer the above code which use If and else by template referenced variable which properly toggle between both icon and non Icon

XPath to select link containing text?

I tried to use this XPath:
//*[contains(normalize-space(text()),'Jira')]
Also tried:
//*[contains(text(),'Jira')]
In the below HTML example, there is space before and after text "Jira". I am not able to click on the link:
<a href="#/crm/usergroup-edit?id=572a3c84e4b07f6189958700"
ng-repeat="gp in groups | filter : userGroupSearch | orderBy:'-name':1"
class="ng-scope">
<div class="inventoryPanel" ng-style="myStyle" style="width: 15.8%;">
<h4 class="ng-binding">
<div class="groupIcon G">
<div class="text ng-binding">P</div>
</div>Jira
</h4>
</div>
</a>
The following XPath will select all a elements whose string value contains a Jira substring:
//a[contains(.,'Jira')]

HTML element to contain id or name from ko.observable using foreach

Below I have a for-each loop using knockout.js.
<div data-bind="foreach:Stuff">
<div class="row">
<span data-bind="text: $data.name"></span>
</div>
</div>
I need to have the HTML Element with an id or name or something that reflects a unique value related to the $data.name value, as another method runs asynchronously, and needs to know which HTML element to update.
Ideally, it would look something like this, I guess:
<div data-bind="foreach:Stuff">
<div class="row">
<span id="data-bind='text: $data.name'" data-bind="text: $data.name"></span>
</div>
</div>
I have found a knockout syntax that applies values during runtime to specified attributes:
<div data-bind="foreach:Stuff">
<div class="row">
<span data-bind="attr: { id: $data.name}"></span>
</div>
</div>
Are you looking for this
<div data-bind="foreach:Stuff">
<div class="row">
<span data-bind="text: $data.name,attr:{id:$data.name}'"></span>
</div>
</div>
Here name is a observable i believe when ever there is change in name in stuff it will automatically updates its value & attr:{id}just to give a dynamic id to element using available bindings .