Observable issue with async pipe - angularjs

im using a library that help me to sort a list with drag-and-drop.
and the list that im giving it is an Observable of the list type, and then im using async to read it in the html, its very simple and looks like this:
#Injectable()
export class MyCmp implements OnInit {
myList: Observable<MyListType[]>;
showingList = false;
constructor(private _myService: MyService) {
};
public showListData(): void {
this.showingList = true;
this.myList = this._myService.getListData();
}
}
And this is the html:
<button md-button
(click)="showListData()"
title="">Show List
</button>
</div>
<md-content>
<div *ngIf="showingList">
<div dnd-sortable-container [sortableData]="myList | async">
<div class="list-bg" *ngFor="#item of myList | async; #i = index" dnd-sortable [sortableIndex]="i">
ID: {{item.id}} <p></p> Name: {{item.name}}
</div>
</div>
<div>Current List {{myList | async | json}}</div>
</div>
</md-content>
now this does not work, BUT, if I do this in my component instead of myList: Observable<MyListType[]>;
I do:
myList = this._myService.getListData();
and then in the html pass myList it works great...
I dont get it!! drive me crazy :/
please help
getListData() like like this:
public getListData(): Observable<MyListType[]> {
return this._someApiService.getCurrentListData().map(res => res.info);
}

Related

Angular 6 : How to display 2 dimension array

This my array data that I get from service:
How I can use this array on my component
<div *ngFor="let i of service$">
<div class="row">
<div class="col-lg-4" *ngFor="let j of i">
{{j.title}}
</div>
</div>
</div>
My component.ts, I call getService() in my constructor.
service$: any;
getService() {
this.serviceService.get_service()
.pipe(first())
.subscribe(
data => {
this.service$ = data;
console.log(this.service$);
},
error => {
this.error = error;
});
}
Use Async pipe which displays the data that comes from API.
<div *ngFor="let i of service$ | async">
<div class="row">
<div class="col-lg-4" *ngFor="let j of i">
{{j.title}}
</div>
</div>
</div>
Your service call should look like
service$: any;
ngOnInit(){
this.service$ = this.serviceService.get_service().pipe(
catchError(error => this.error = error)
);
}
Your have some issues in TS I believe. First of all define variable like :
service$: any[] = [];
Then remove pipe() and use below code :
getService() {
this.serviceService.get_service()
.subscribe(
data => {
this.service$ = data;
console.log(this.service$);
},
error => {
this.error = error;
});
}
I hope you are returning get_service() some thing like this :
return this.http.get('YOUR_URL')
.map((response) => response.json());
Your HTML looks fine to me.

Get into Firebase complex object containing another object

I've got Angular2 project connected directly with Firebase.
The structure of my database is presented in the picture below. So we've got couple of objects.
Main is orders, then the key od order, some extra information and another object "items" which contains several objects like 0, 1 etc. Each of them has a object called "product" which has some other parameters...
orders
-> datePlaced,
items
-> 0
-> quantity, totalPrice, product
->
imageUrl,
price,
title
My point is that when I'm creating "My Orders" tab, I'd like to get information of every item in specific order e.g. I see list of orders, and small button "View order", I click and I see details about this order with special key.
I prepared view with orders, buttons but I cannot take any objects form object orders, I've got a blank page.
order-details.component.ts
export class OrderDetailsComponent implements OnInit, OnDestroy {
order$;
userId: string;
userSubscription: Subscription;
constructor(private orderService: OrderService, private authService: AuthService) {}
async ngOnInit() {
this.userSubscription = this.authService.user$.subscribe(user => this.userId = user.uid);
this.order$ = this.authService.user$.switchMap(u => this.orderService.getOrdersByUser(u.uid));
}
ngOnDestroy() {
this.userSubscription.unsubscribe();
}
}
order-details.component.html
<div class="card" *ngIf="order$ | async as order">
<div class="card-body">
<h5 class="card-title">Your Order</h5>
<p class="card-text">You ordered {{ order.datePlaced | date }} items</p>
<ul class="list-group list-group-flush">
<li *ngFor="let order of order.shipping" class="list-group-item">
{{ order.city }} x {{ order.city }}
<div class="float-right">
{{ order.totalPrice | currency:'USD':'symbol' }}
</div>
</li>
<li class="list-group-item font-weight-bold">
Total
<div class="float-right">
{{ order.totalPrice | currency:'USD':'symbol' }}
</div>
</li>
</ul>
</div>
</div>
order.service.ts
export class OrderService {
constructor(private db: AngularFireDatabase, private shoppingCartService: ShoppingCartService) { }
async placeOrder(order) {
let result = await this.db.list('/orders').push(order);
this.shoppingCartService.clearCart();
return result;
}
getOrders() {
return this.db.list('/orders');
}
getOrdersByUser(userId: string) {
return this.db.list('/orders', {
query: {
orderByChild: 'userId',
equalTo: userId
}
});
}
}
How can I get every parameter from complex object "orders"?
I solved this by taking param routes in my order-details.component.ts and then a create function getOrder(id) in order service. When you have id of your order it's quite simple to take object from database.

Two way binding with pipe not binding in angular2

In my component html displaying the data based on the current year using the filter, it works fine on load. If i do push or pop on the variable updating the html also, but i use filter (pipe) not updating the html view.
onSubmit pushing the new data value to the projects (appropriate), it's reflecting (updating the html) If didn't use filter.
data.component.ts
constructor() {
this.projects = (from service getting the data);
var newDate = new Date();
newDate.setDate(1);
this.dateValue = newDate;
}
onSubmit(data) {
this.projects.push(data);
}
data.component.html
<ul class="list-group">
<li *ngFor="let event of projects | yearFilter: dateValue" class="list-group-item">
<span class="event_release">{{event.startDate | date: 'dd/MM/yyyy'}} </span><br />
<strong>{{event.title}}</strong>
</li>
</ul>
<ul class="list-group">
<li *ngFor="let data of projects" class="list-group-item">
<span class="event_release">{{data.startDate | date: 'dd/MM/yyyy'}} </span><br />
<strong>{{data.title}}</strong>
</li>
</ul>
year-filter.pipe.ts
export class YearFilterPipe implements PipeTransform {
transform(items: any[], args: any): any {
return items.filter(item => {
var startDate = new Date(item.startDate);
var endDate = new Date(item.endDate);
var realEndDate = new Date(item.realEndDate);
return ((startDate.getFullYear()===args.getFullYear());
});
}
}
In your Pipe use this:
#Pipe({ name: 'yearFilter', pure: false })
Your need to set properties pure to false. By default is true.

Filter object array with pipe Angular 2

I have a
class:
export class Todo {
public id: number;
public name: string;
public isCompleted: boolean;
public dateCreated: Date;
public userName: string;
}
A service:
getTodos(): Observable < Todo[] > {
return this.http.get(this.todosUrl)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body || {};
}
In my component:
getTodos(){
this.todoService.getTodos()
.subscribe(
todos => this.todos = todos,
error => this.errorMessage = <any>error
);
}
And html file:
<div class="ui large selection animated divided list">
<a *ngFor="let todo of (todos | todoFilter:false)" class="item">
<div class="right floated content">
<div class="ui vertical animated negative button" tabindex="0">
<div class="hidden content">Delete</div>
<div class="visible content">
<i class="fa fa-trash" aria-hidden="true"></i>
</div>
</div>
</div>
<i class="minus square outline icon"></i>
<div class="content">
<div class="header">{{todo.name}}</div>
<div class="description">{{todo.dateCreated | date:"MMM-dd-yyyy"}}</div>
</div>
</a>
</div>
The problem is, when I try to use this pipe to filter the completed todos, I keep getting an error that say Cannot read property filter of undefined.
Did I do something wrong or are there any ways to filter it without using an pipe?
My pipe:
transform(allTodos: Todo[], args?: boolean){
if (allTodos === null) {
return null;
}
return allTodos.filter(todo => todo.isCompleted);
}
Thank you.
Try to replace the if (allTodos === null) to just if (!allTodos)
I think the problem is that you're getting to the .filter even while your this.todos is still empty since you're only checking that it isn't null.

What could be a quick and fast way for reordering UI list?

Im using Angular 2 & Typescript .
In my project im presenting a simple list of json objects, the html looks like this:
<div>
<!-- Present List Button -->
<button md-button
(click)="showList()"
class="md-primary"
title="show list">Cropping</button>
</div>
<md-content>
<div *ngIf="showList">
<div class="list-bg" *ngFor="#list of lists | async">
ID: {{list.id}} <p></p> Number of Items: {{list.numberOfItems}}
</div>
</div>
</md-content>
very simple list.
Now I want some kind of method to reorder this list and set the lists array to the new order.
Im looking for a method that a user cal reorder the list however he wants, like change the list by priority.
Could someone please help me to find a method that will be quick to implement and will work good?
(I looked into some drag and drop libraries but I work with specific ver of Angular 2 (2.0.0-beta.15) which non of them support.)
Thanks allot!
for this you have to use angular 2 pipe for more information check this
orderBy Pipe
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: "orderBy",
pure: false,
})
export class OrderBy implements PipeTransform {
transform(array: any, args: any) {
if (array != null) {
if (array) {
let orderByValue = args;
let byVal = 1
if (orderByValue.charAt(0) == "!") {
byVal = -1
orderByValue = orderByValue.substring(1)
}
array.sort((a: any, b: any) => {
if (a[orderByValue].toString().toLowerCase() < b[orderByValue].toString().toLowerCase()) {
return -1 * byVal;
} else if (a[orderByValue].toString().toLowerCase() > b[orderByValue].toString().toLowerCase()) {
return 1 * byVal;
} else {
return 0;
}
});
return array;
}
}
}
}
Component
import {Filter} from '../pipes/filter';
import {OrderBy} from '../pipes/orderBy';
#Component({
selector: 'category',
templateUrl: '../views/category.component.html',
directives: [ROUTER_DIRECTIVES],
providers: [SetupService, HTTP_PROVIDERS],
pipes: [ OrderBy]
})
View for ascending order
<md-content>
<div *ngIf="showList">
<div class="list-bg" *ngFor="#list of lists | async | orderBy:'id'">
ID: {{list.id}} <p></p> Number of Items: {{list.numberOfItems}}
</div>
</div>
</md-content>
View for descending order
<md-content>
<div *ngIf="showList">
<div class="list-bg" *ngFor="#list of lists | async | orderBy:'!id'">
ID: {{list.id}} <p></p> Number of Items: {{list.numberOfItems}}
</div>
</div>
</md-content>

Resources