ngIf check if object is empty [done] - javascript

i have a list name "day".
export class Day{
id:number;
name: string;
items: Object;
}
i want to display "Hello" when items is empty. I try to used *ngIf but it doesn't work.
This is my code.
<div class=" list" *ngFor="let day of days">
<div class="list-name">
<strong>
{{day.name}}
</strong>
<div *ngIf= "day.items === 0">
Hello
</div>
</div>
<div *ngFor="let item of day.items">
<div class="column" [style.background-image]="'url(' + item.photoPath + ')'">
<h4 class="item-name">{{item.name}}</h4>
</div>
</div>
</div>

You have to use length to check the array size
<div *ngIf= "day.items?.length === 0">

Try this
<div *ngIf= "day.items.length === 0">

You can use <div *ngIf= "day.items == null || day.items.length === 0"> for check items is null or empty.
Demo https://stackblitz.com/edit/angular-scssrw

As I seem items is not an array. It is an object. Using ngFor over an Object would resuslt in an error.
Secondly, you should use .length over an array to get the count of Objects. so it should be as,
<div *ngIf= "day?.items?.length === 0">

You can simply make use of conditional statement expression inside your interpolation without using 'ngIf'.
...
<strong>
{{ (day.item && day.item?.length) ? day.name : day.name + 'Hello' }}
</strong>
...

Actually the question is about finding the length of object that is only possible using Object.keys(myObj).length. In Angular you can use it as:
in .ts file:
objectKeys = Object.keys;
in html file:
<div *ngIf="objectKeys(myObj).length > 0"></div>
Here is the reference:
https://stackblitz.com/edit/angular-object-length-xzxajl?file=app%2Fapp.component.html

Related

How to start loop from index 1 instead of index 0 in *ngFor loop in angular?

I am currently getting some data from a dummy api, data from response starts from 1 and the index is currently starting from 0.
How I can start the index loop from 1 instead of 0?
Following the html for *ngFor below:
component.html
<div class="all-users" >
<div class="nested-items" *ngFor="let data of flattenedResponse[0]; let i=index; " (click)="switchUsers(i)">
<h4>{{i}}</h4>
<img src="{{data.image}}" alt="profile">
</div>
</div>
Why not just do the following:
<div class="all-users" >
<div class="nested-items" *ngFor="let data of flattenedResponse[0]; let i=index; " (click)="switchUsers(i)">
<h4>{{i + 1}}</h4>
<img src="{{data.image}}" alt="profile">
</div>
</div>
I don't know of a way to change where the index starts, but this way works fine for most cases
How I can start the index loop from 1 instead of 0
The correct answer here is... you can't.
So there are some suggestions already, but personally I would avoid hacking your markup to get round the data structure the api returns. It's generally a bad idea to make your markup need to know too much about what your server does.
If the array your api returns is not in the best format for your markup - just create a new data array which is, and point your markup at that. It's best to do this in a service at the point you handle the api result, but if nothing else, do it in your .ts file.
have you try :
<div class="all-users">
<div class="nested-items" *ngFor="let data of flattenedResponse[0]; let i=index; " (click)="switchUsers(i+1)">
<h4>{{i+1}}</h4> <img src="{{data.image}}" alt="profile">
</div>
</div>
or you can just skip first element like this :
<div class="nested-items" *ngFor="let data of flattenedResponse[0] | slice:1; let i=index; " (click)="switchUsers(i)"></div>
You can skip first index explicitly with *ngIf:
<div class="all-users" >
<div class="nested-items" *ngFor="let data of flattenedResponse[0]; let i=index;" (click)="switchUsers(i)">
<ng-container *ngIf="index !== 0">
<h4>{{i}}</h4>
<img src="{{data.image}}" alt="profile">
</div>
</ng-container>
</div>
</div>

Loop variables in Vue.js similar to AngularJS

I my vue.js application I want to know the last repeated element in a v-for directive. I know there is something similar in angularjs with the $last loop variable in its ngRepeat directive:
<div ng-repeat="(key, value) in myObj">
<span ng-if="$last">Shows if it is the last loop element</span>
</div>
Is there any equivalent in vue.js which I am not aware of or do I have to implement some own logic?
It works for me :)
<div v-for="(item, index) in items">
<span v-if="index === (items.length-1)">This is the last loop element</span>
</div>
you can also put the logic in a computed property :
<div v-for="(value, key) in myObj">
<span v-if="key === last">This is the last loop element : {{ value }}</span>
</div>
//...
computed: {
last() {
let keys = Object.keys(this.myObj)
return keys.slice(-1)[0]
}
}
fiddle here
There's no equivalent for this in Vue, no.
You can do this instead, check for index if it is last
<div v-for="(value, key, index) in myObj">
<div v-if="index === Object.keys(myObj).length-1"> my content</div>
</div>
You can try this
<div v-repeat="myObj">
<span v-if="$index === (myObj.length-1)">Shows if it is the last loop element</span>
</div>
Based on #Nisha answer I have been doing this:
<template v-for="(obj, index) in originalData">
<template v-if="index == 0 || (index >= 1 && obj.valueA !== originalData[index - 1].valueA)">
{{ obj.valueA }}
</template>
</template>
I want the loop to always happen the first time, but to conditionally check a value for every loop afterwards. I am using <template> tags to avoid outputting unnecessary markup. In my example originalData is an array of objects.

How to check condition inside map without putting a div

I am trying to put a "col-sm-6" inside a row with checking a condition . But when null value is coming it is returning a blank div with ".col-sm-6" class, I need to hide that class when value is null.
<div className="row">
{attribute.attributeValues.map((list, index) =>
<div className="col-sm-6" >
{list.isSelected === 1 ?
<div className="style">
<span><i className="fa fa-check"></i>{list.tag_value}</span>
</div>:''
}
</div>
)}
</div>
this is giving results like:
like:
<div class="row">
<div class="col-sm-6">Some Value</div>
<div class="col-sm-6"></div>
<div class="col-sm-6"></div>
</div>
But I want:
<div class="col-sm-6">Some Value</div>
<div class="col-sm-6">Some Value</div>
<div class="col-sm-6">Some Value</div>
You can make use of React.Fragment like
<div className="row">
{attribute.attributeValues.map((list, index) =>
<React.Fragment key={index}>
{list.isSelected === 1 ?
<div className="style">
<span><i className="fa fa-check"></i>{list.tag_value}</span>
</div>:''
}
</React.Fragment>
)}
</div>
According to the docs:
A common pattern in React is for a component to return multiple
elements. Fragments let you group a list of children without adding
extra nodes to the DOM.
Second method to remove the wrapping {} in the ternary condition
<div className="row">
{attribute.attributeValues.map((list, index) =>
list.isSelected === 1 ?
<div className="style">
<span><i className="fa fa-check"></i>{list.tag_value}</span>
</div>: null
)}
</div>
Actually, you just need to use filter (MDN documentation) before the map. You can do something like:
attribute.attributeValues.filter(list => list.tag_value).map(...
That way, with filter, you return a new Array in which only items with a "real" list.tag_value value.
In JavaScript, everything without a "Value" is False (JavaScript Booleans). That means that the filter above will filter out any list.tag_value equal to: undefined, null, empty String ("") or Number equal to 0.

ng-repeat inside of ng-repeat- filters not working

I am displaying the ng-repeat content in two columns.
Using this code works fine:
<div class=storerow ng-repeat="store in stores track by $index" ng-if="$index%2==0">
<div ng-repeat="i in [$index,$index+1]" ng-if="stores[i]!=null" class="ngrepeatstore">
<div class="image-container" style="background-image: url({{stores[i].image}})" ng-click="tileClicked({{stores[i].id}})">
</div>
</div>
However, when I add a filter- it breaks the NG repeat and no content appears:
<div class=storerow ng-repeat="store in stores track by $index" ng-if="$index%2==0">
<div ng-repeat="i in [$index,$index+1] | filter: greaterThan('order', 0) | orderBy:'order'" ng-if="stores[i]!=null" class="ngrepeatstore">
<div class="image-container" style="background-image: url({{stores[i].image}})" ng-click="tileClicked({{stores[i].id}})">
</div>
</div>
the .js for greaterThan
$scope.greaterThan = function(prop, val){
return function(item){
return item[prop] > val;
}}
I tried adding the filter to the first ng-repeat- however that doesn't work as it just applies the filter to the overall content (ie if just one item is greatThan 0, it shows all items- not just the ones greater than 0).
This is because you're actually telling Angular to filter the property order on [$index, $index + 1], an array of two integers, which makes no sense.
I.E. With your delegate comparing index.prop > val, what you're really doing is comparing index['order'] > someValue.
This Plunker demonstrates: http://plnkr.co/edit/FkSrmZuuK4B1ToGNgAnq?p=preview You need to move filter:greaterThan(prop, val) up to the parent ng-repeat. Only there will your filter work.
<div ng-repeat="store in stores | filter:greaterThan2('id', 0) | orderBy:'name'" ng-if="$even">
{{store.name}}
<div ng-repeat="i in [$index, $index+1] | orderBy:angular.identity:true" ng-if="stores[i] !== null">
<strong>store.id</strong> {{i}}
</div>
</div>

How to disable a div and all elements inside div?

My problem is, I want to disable div. I ma not getting a way to do it.
<div ng-repeat="item in items">
<div ng-click="somefunction()">{{some value}}</div>
</div>
JS:
$scope.items = [1,2,3,4,5];
I want to disable all div having even value.
Divs cannot be disabled by HTML. You can do it by code:
<div ng-click="somefunction(item)">{{some value}}</div>
$scope.somefunction = function(item) {
if( item % 2 === 0 ) {
return;
}
// rest of logic as before
};
You cant disable div. but you can disable link or button like:
<div ng-repeat="item in items">
<a ng-click="somefunction()" ng-disabled="disabledEvenItems(item)">{{some value}}</a>
</div>
Or you can add style base on it:
<div ng-repeat="item in items">
<div ng-click="somefunction()" ng-class="{{'myClass': disabledEvenItems(item)}}">{{some value}}</div>
</div>
</div>
$scope.disabledEvenItems = function(item) {
return item % 2 !== 0
};
To run the function only for odd values you can use $even / $odd helper properties ngRepeat offers:
<div ng-repeat="item in items">
<div ng-click="$even && somefunction()">{{some value}}</div>
</div>
UPD.
Angular way of doing what you are after is to use expression like this:
<div ng-click="item % 2 && somefunction()">{{some value}}</div>
Try this :
remove onclick from div as shown below
<div ng-repeat="item in items" class="divList">
<div>{{some value}}</div>
</div>
use .filter() to find div with even values and detach click handler
$(function(){
$('.divList div').click(somefunction());
$('.divList div').filter(function(){
var value = parseInt($(this).text()) || 0;
return (value % 2 ==0);
}).off('click');
});
Use display:none
<div id="someId" style="display: none;">
visibility: hidden hides the element, but it still takes up space in the layout.
display: none removes the element completely from the document, it doesn't take up any space.

Categories