Incrementing date in angular template - html

I have something like below and i need to display dates incrementally
<ul>
<li *ngFor="let item of items">
<h2>
{{item.name}}
</h2>
<p >
{{item.description}}
</p>
<time>{{date | date:'dd/MM/yyyy'}}</time>
</li>
</ul>
dates need to be shown as for first item it shows today's date and then tomorrow and so on.
If there is a way that it can be done only by using html template then its better. Or just help with the best way to do this.

I don't think there is a way to do this with only the date pipe, its primary use is morphing a current date into a different display. Not adding/removing. Something you could do is create your own date pipe that has an offset option
Solution 1
Creating a new pipe and using the moment library
import {Pipe, PipeTransform} from '#angular/core';
import * as moment from 'moment';
#Pipe({name: 'customDate'})
export class CustomDatePipe implements PipeTransform {
transform(date, format = 'dd/MM/yyyy', dayOffset = 0, monthOffset = 0, yearOffset = 0) {
return moment(new Date(date)).add(dayOffset, 'days')
.add(monthOffset, 'months')
.add(yearOffset, 'years')
.format(format);
}
}
and then reference it in html as this
<ul>
<li *ngFor="let item of items; let i = index">
<span>{{date | customDate: 'dd/MM/yyyy': i}}</span>
</li>
</ul>
Solution 2
Or you can use vanilla javascript Date along with a custom pipe
import {Pipe, PipeTransform} from '#angular/core';
#Pipe({name: 'customDate'})
export class CustomDatePipe implements PipeTransform {
transform(date, format = 'dd/MM/yyyy', dayOffset = 0) {
return new Date(date).addDays(dayOffset);
}
}
and reference it like this
<ul>
<li *ngFor="let item of items; let i = index">
<span>{{date | customDate: i | date: 'dd/MM/yyyy'}}</span>
</li>
</ul>

Related

Display content of a list in Angular 2?

I am new in Angular. I am creating a component in which I am creating a list of int. An example of the content of the list is 13,14,15,22,23,24.
I want to display this content on screen in a specific way. I want the continiously integeres to be in one line and the others in the second line. For example I want this:
13:00, 14:00, 15:00 button
22:00, 23:00, 24:00 button
I am trying this but I don't want a continious list, I want two parts of the list.
<ul>
<li *ngFor="let int of listindexdisabled">{{int}}:00 </li>
</ul>
Can someone help?
Why don't we try to set up two loops with a SlicePipe to iterate on a portion ( 13 -> 15 and second loop 2 -> 24 )?
If you have non dynamic list and you list will always need to be cut at a certain index , this should help you
https://angular.io/api/common/SlicePipe
<ul>
<li *ngFor="let int of listindexdisabled | slice:0:3">
{{int}}:00
</li>
</ul>
<ul>
<li *ngFor="let int of listindexdisabled | slice:3:6">
{{int}}:00
</li>
</ul>
otherwise , i think that this should works
<ul>
<ng-container *ngFor="let int of listindexdisabled">
<li *ngIf="int < 22">
{{int}}:00
</li>
</ng-container>
</ul>
<ul>
<ng-container *ngFor="let int of listindexdisabled">
<li *ngIf="int > 21">
{{int}}:00
</li>
</ng-container>
</ul>
You can try this below code
<ul>
<li *ngFor="let int in listindexdisabled">{{int}} : 00</li>
</ul>
Here is a sample of what you could do: repro on Stackblitz
And in case stackblitz is not working, here is the code :
.html :
<ul *ngFor="let chunk of displayedValues">
<li>
<span *ngFor="let value of chunk">{{value}}:00 - </span>
</li>
</ul>
.ts :
import { Component, OnInit } from '#angular/core';
import { getAttrsForDirectiveMatching } from '#angular/compiler/src/render3/view/util';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
values = [13,14,15,18,19,22,23,24];
displayedValues = [];
ngOnInit(){
this.customChunk();
}
customChunk(){
let array = [];
this.values.forEach(val => {
if(array.length === 0
|| val === array[array.length-1] + 1){
array.push(val);
} else {
this.displayedValues.push(array);
array = [];
}
});
// add the last chunk
this.displayedValues.push(array);
}
}
The idea is to rework your array into an array of chunk made by numbers that follow themselves. Then you just have to do a loop inside a loop to display your values.

How to display array item in Angular

I am a newbie in Angular, I create an array but I have problem to display it.
When I display the array item it is blank.
write.component.html:
<div class="data">
<li> Name: <input type="text" [(ngModel)]="name" placeholder="Please enter Name" ></li>
<li> Age:<input type="text" [(ngModel)]="age" placeholder="Please enter Age" class="age"></li>
<li>College:<input type="text" [(ngModel)]="college" placeholder="Please enter College" ></li>
</div>
<h2>Student</h2>
<ul class="details">
<li>
<span class="badge" *ngFor="let student of students"> // display array item
{{student.name}}{{student.age}}{{student.college}}</span>
</li>
</ul>
.ts
export class WriteComponent implements OnInit {
name : string;
age : number;
college : string;
students : Array<any>; // declare array
}
write-service.ts
import { Injectable } from "#angular/core";
#Injectable()
export class HomeService {
private students = new Array<any>( //array details
{
name:"dwq",
age:12,
college:"2321"
}
)
}
After you create the service you have to inject that service to your component like this
constructor(private homeServ:HomeService) { }
then the service will be avilable in the componnet you can get the data
ngOnInit(){
this.students = this.homeServ.getStudents();
}
demo 🚀
you can remove the injectable decorator from the service if the service has no dependency
read more about angular services 👉 her

change background color based on response attributes Angular

I had request data from API, then I got response Object, so using *ngFor, I had managed to display some data that I want, problem is that are some css need to be implemented based on response attribute, for my data, I had list of bank and status. based on attribute status Offline
I need to change background color and need only show Offline status only.I had managed to change the background color, this is what I had tried:
html file
<ul class="ul1">
<li
[style.background]="getBackgroundColor(p.status)"
class="li1" *ngFor="let p of myData?.paymentChannels">
<span>{{p.name}}</span>
<br>
<span>{{p.status}}</span>
</li>
</ul>
ts file
getBackgroundColor(status) {
switch (status) {
case 'Offline':
return 'grey';
}
}
expected output:
also this is my stackblitz demo, I could use some suggestion to solve mine.
I would suggest something like this:
<ul class="ul1">
<li
[ngClass]="{offline: p.status == 'Offline'}"
class="li1" *ngFor="let p of myData?.paymentChannels">
<span>{{p.name}}</span>
<br>
<span> {{p.status == 'Offline' ? p.status : ' '}}</span>
</li>
</ul>
And add to css:
.offline {
background-color: gray;
}
your code is working but I think it's better without function like this:
<ul class="ul1">
<li [style.background]="'grey' : p.status == 'Offline'" class="li1"
*ngFor="let p of myData?.paymentChannels">
<span>{{p.name}}</span>
<br>
<span>{{p.status}}</span>
</li>
</ul>
Before
<span>{{p.status}}</span>
After
<span>{{p.status === 'Offline' ? 'Offline' : ' '}}</span>
It would be even better if you would extract the logic to a method withing the TS file.
The ' ' part is a placeholder (blank space) so the box do not collapse, but I would recommend adding the proper CSS styling, for instance, adding min-height: 36px; to the class .li1 would suffice.
StackBlitz
You can filter your data using structural directive *ngIf and then apply styling:
<ul
*ngIf="myData?.paymentChannels"
class="ul1">
<li
[style.background]="p?.status === 'Offline'? 'grey' : 'green'"
class="li1"
*ngFor="let p of myData?.paymentChannels">
<ng-container *ngIf="p?.status === 'Offline'">
<span>{{p.name}}</span>
<br>
<span>{{p.status}}</span>
</ng-container>
</li>
</ul>
If you want to filter and your array of data is small, then you can use *ngIf directive. However, it would be better to use filter pipe:
<li *ngFor="let item of myData?.paymentChannels | yourFilter:filterargs">
and your pipe:
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'myfilter',
pure: false
})
export class YourFilterPipe implements PipeTransform {
transform(items: any[], filter: Object): any {
if (!items || !filter) {
return items;
}
// filter items array, items which match and return true will be
// kept, false will be filtered out
return items.filter(item => item.title.indexOf(filter.title) !== -1);
}
}
and you should include your pipe into app.module.ts:
import { YourFilterPipe } from './shared/pipes/your-filter.pipe';
#NgModule({
imports: [
..
],
declarations: [
YourFilterPipe,
],
providers: [
..
],
bootstrap: [AppComponent]
})
export class AppModule { }
Please, see the example at stackblitz.com
UPDATE:
If you do not want to filter data, but hide status offline you can use *ngIf structural directive:
<ul
*ngIf="myData?.paymentChannels"
class="ul1">
<li
[style.background]="p?.status === 'Offline'? 'grey' : 'green'"
class="li1"
*ngFor="let p of myData?.paymentChannels">
<span>{{p.name}}</span>
<br>
<span *ngIf="p?.status === 'Offline'; else empty">{{p.status}}</span>
<ng-template #empty>$nbsp;</ng-template>
</li>
</ul>

Using ng-repeat or ngFor to display each object in a JSON object as individual list items

I recieve an object that looks like this:
I'm trying to use ng-repeat to display the "Message", "Priority" and "DateTime" properties of each object as li items in a ul.
I've tried a couple of approaches including ng-repeat and ngFor, where all have been wrapped in divs like the first option:
This seems like the proper way to do it, but returns exactly nothing:
<div style="background: red;">
<ul>
<li ng-repeat="Notification in allNotifications">{{Notification}}</li>
</ul>
</div>
This option returns the specific object as expected:
<li style="border-radius: 3px"
[ngStyle]="{'color' : alertText}" >
Notification: {{ allNotifications.Notifications['0'].Message['0'] }}
</li>
Doesnt compile:
<li style="border-radius: 3px"
[ngStyle]="{'color' : alertText}"
[ngFor]="let subItem of allNotifications.Notifications['0'].Message['0']">
Notification: {{ subItem }}
</li>
My TS looks like this:
export class EventLogComponent implements OnInit {
constructor(private _dashdata: DashdataService) { }
NotificationName: string;
alertText: string;
allNotifications: JSON;
ngOnInit() {
this.NotificationName = 'NoNameAvailable';
this.alertText = 'Black'; //TODO: set color according to threatlevel
setInterval(() => {
this._dashdata.getAllNotifications()
.subscribe(res => {
this.allNotifications = res['notificationdata'];
console.log(this.allNotifications);
});
}, 5000); // Data Update interval in MS
}
}
ng-repeat is directive of framework AngularJS.
You are using Angular so in your case you should use ngFor:
<div style="background: red;"> <ul> <li *ngFor="let notification of allNotifications">{{notification}}</li> </ul> </div>
Using angular you should forget ng-repeat that is apart of AngularJS (version <= 1.6)
I think you have a double problem, the first one, as said, is ng-repeat, the second one is that you are not well targeting your data.
Try this
template
<div style="background: red;">
<ul>
<li *ngFor="let not of allNotifications.Notification">{{not}}</li>
</ul>
</div>

Adding a click event to a list of iterations with ngfor

I'm developing an app and so far this is what I have achieved. I have my individual flights displaying horizontally in a list that I can scroll through:
What I want is that when I click on an individual flight, its details will pop up / be shown on the screen. So my next step is figuring out how to add a click event to these flight iterations so that the selectFlight method will be called.
My Code:
flight-viewer.html:
<h3>Flights </h3>
<div>
<ul class= "grid grid-pad">
<a *ngFor="let flight of flights" class="col-1-4">
<li class ="module flight">
<h4>{{flight.number}}</h4>
</li>
</a>
</ul>
</div>
flight.viewer.component.ts:
#Component({
selector: 'flight-viewer',
templateUrl: 'app/flight-viewer.html',
styleUrls: ['app/flight-viewer.css']
})
export class FlightViewerComponent {
name = 'FlightViewerComponent';
errorMessage = "";
stateValid = true;
flights: Flight[];
selectedFlight: Flight;
flightToUpdate: Flight;
constructor(private service: FlightService) {
this.selectedFlight = null;
this.flightToUpdate = null;
this.fetchFlights();
}
flightSelected(selected: Flight) {
console.log("Setting selected flight to: ", selected.number);
this.selectedFlight = selected;
}
flight.row.component.ts:
#Component({
selector: '[flight-row]',
templateUrl: 'app/flight-row.html',
styleUrls: ['app/flight-row.css']
})
export class FlightRowComponent {
#Input()
flight: Flight;
#Output()
onFlightSelected = new EventEmitter<Flight>();
#Output()
onFlightUpdating = new EventEmitter<Flight>();
name = 'FlightRowComponent';
selectFlight() {
console.log("Just selected ", this.flight.number, " for display");
this.onFlightSelected.emit(this.flight);
}
Somehow I need to add a click event like this : (click)="selectFlight() on to each of the li elements (each individual flight)..
Can someone help me with this? I'm new to developing in angular with HTML & CSS.
Thanks in advance.
Edit:
old flight-viewer.html
<!--
<h3>{{errorMessage}}</h3>
<flight-selected [flight]="selectedFlight"></flight-selected>
<table *ngIf="stateValid">
<thead>
<tr>
<th>#</th>
<th>Origin</th>
<th>Departure Time</th>
<th>Destination</th>
<th>Arrival Time</th>
<th><!– Select link –></th>
<th><!– Update link –></th>
</tr>
</thead>
<tbody>
<tr flight-row
[flight]="current"
(onFlightSelected)="flightSelected($event)"
(onFlightUpdating)="flightUpdating($event)"
*ngFor="let current of flights"></tr>
</tbody>
</table>
<div *ngIf="flightToUpdate">
<flight-update [flight]="flightToUpdate"
(onFlightUpdated)="updateFlight($event)"></flight-update>
</div>
-->
flight-row.html:
<td>{{flight.number}}</td>
<td>{{flight.origin}}</td>
<td>{{flight.departure | date}}</td>
<td>{{flight.destination}}</td>
<td>{{flight.arrival | date}}</td>
<td><span (click)="selectFlight()">Select</span></td>
<td><span (click)="updateFlight()">Update</span></td>
Do i need something in my flight-viewer.html such as onFlightSelected ="flightSelected($event)"?
flight-viewer.html:
<div>
<ul class= "grid grid-pad">
<a *ngFor="let flight of flights" class="col-1-4">
<li class ="module flight" (click)="selectFlight(flight)">
<h4>{{flight.number}}</h4>
</li>
</a>
</ul>
flight.row.component.ts:
#Component({
selector: '[flight-row]',
templateUrl: 'app/flight-row.html',
styleUrls: ['app/flight-row.css']
})
export class FlightRowComponent {
#Input()
flight: Flight;
#Output()
onFlightSelected = new EventEmitter<Flight>();
#Output()
onFlightUpdating = new EventEmitter<Flight>();
name = 'FlightRowComponent';
selectFlight(flight) {
console.log("Just selected ", this.flight.number, " for display");
this.onFlightSelected.emit(this.flight);
}
you have to pass that parameter of flight in selectFlight(flight) and the function will accept this parameter and return that particular info of flight
All the best.
for any query write your comment