2017-10-14 48 views
7

Używam tabeli mat w celu wyświetlenia zawartości wybranych języków. Mogą również dodawać nowe języki za pomocą panelu dialogowego. Po dodaniu języka i zwróceniu go chcę odświeżyć źródło danych, aby pokazać zmiany, które wprowadzili.Angular + Material - odświeżanie źródła danych (mat-table)

Inicjuję magazyn danych, pobierając dane użytkownika z usługi i przekazując je do źródła danych w metodzie odświeżania.

Language.component.ts

import { Component, OnInit } from '@angular/core'; 
import { LanguageModel, LANGUAGE_DATA } from '../../../../models/language.model'; 
import { LanguageAddComponent } from './language-add/language-add.component'; 
import { AuthService } from '../../../../services/auth.service'; 
import { LanguageDataSource } from './language-data-source'; 
import { LevelbarComponent } from '../../../../directives/levelbar/levelbar.component'; 
import { DataSource } from '@angular/cdk/collections'; 
import { Observable } from 'rxjs/Observable'; 
import 'rxjs/add/observable/of'; 
import { MatSnackBar, MatDialog } from '@angular/material'; 


@Component({ 
    selector: 'app-language', 
    templateUrl: './language.component.html', 
    styleUrls: ['./language.component.scss'] 
}) 
export class LanguageComponent implements OnInit { 

    displayedColumns = ['name', 'native', 'code', 'level']; 
    teachDS: any; 

    user: any; 

    constructor(private authService: AuthService, private dialog: MatDialog) { } 

    ngOnInit() { 
    this.refresh(); 
    } 

    add() { 
    this.dialog.open(LanguageAddComponent, { 
     data: { user: this.user }, 
    }).afterClosed().subscribe(result => { 
     this.refresh(); 
    }); 
    } 

    refresh() { 
    this.authService.getAuthenticatedUser().subscribe((res) => { 
     this.user = res; 
     this.teachDS = new LanguageDataSource(this.user.profile.languages.teach); 
    }); 
    } 
} 

język-data-source.ts

import {MatPaginator, MatSort} from '@angular/material'; 
import {DataSource} from '@angular/cdk/collections'; 
import {Observable} from 'rxjs/Observable'; 
import 'rxjs/add/observable/merge'; 
import 'rxjs/add/operator/map'; 

export class LanguageDataSource extends DataSource<any> { 

    constructor(private languages) { 
    super(); 
    } 

    connect(): Observable<any> { 
    return Observable.of(this.languages); 
    } 

    disconnect() { 
    // No-op 
    } 

} 

Więc starałem się wywołać metodę odświeżania gdzie mogę uzyskać od użytkownika backend, a następnie ponownie zainicjuję źródło danych. Jednak to nie działa, nie ma żadnych zmian.

Odpowiedz

6

wywołać wykrywanie zmian za pomocą ChangeDetectorRef w metodzie refresh() tuż po otrzymaniu nowych danych, wstrzyknąć ChangeDetectorRef w konstruktorze i używać detectChanges takiego:

import { Component, OnInit, ChangeDetectorRef } from '@angular/core'; 
import { LanguageModel, LANGUAGE_DATA } from '../../../../models/language.model'; 
import { LanguageAddComponent } from './language-add/language-add.component'; 
import { AuthService } from '../../../../services/auth.service'; 
import { LanguageDataSource } from './language-data-source'; 
import { LevelbarComponent } from '../../../../directives/levelbar/levelbar.component'; 
import { DataSource } from '@angular/cdk/collections'; 
import { Observable } from 'rxjs/Observable'; 
import 'rxjs/add/observable/of'; 
import { MatSnackBar, MatDialog } from '@angular/material'; 


@Component({ 
    selector: 'app-language', 
    templateUrl: './language.component.html', 
    styleUrls: ['./language.component.scss'] 
}) 
export class LanguageComponent implements OnInit { 


    displayedColumns = ['name', 'native', 'code', 'level']; 
    teachDS: any; 

    user: any; 

    constructor(private authService: AuthService, private dialog: MatDialog, private changeDetectorRefs: ChangeDetectorRef) { } 

    ngOnInit() { 

    this.refresh(); 

    } 

    add() { 
    this.dialog.open(LanguageAddComponent, { 
     data: { user: this.user }, 
    }).afterClosed().subscribe(result => { 
     this.refresh(); 
    }); 
    } 



    refresh() { 
    this.authService.getAuthenticatedUser().subscribe((res) => { 
     this.user = res; 
     this.teachDS = new LanguageDataSource(this.user.profile.languages.teach); 
     this.changeDetectorRefs.detectChanges(); 
    }); 

    } 

} 
+0

To wydaje się działać, czy to właściwy sposób? Wydaje się nieco hacky ... – KHAN

+0

Jakie są inne sposoby? Czy możesz podać przykłady w rozwiązaniu, aby uzyskać pełną odpowiedź? – KHAN

+0

Używam tylko tego w moich projektach właśnie teraz. – HDJEMAI

1

Ponieważ używasz MatPaginator, wystarczy aby wykonać jakąkolwiek zmianę w paginatorze, powoduje to ponowne załadowanie danych.

Prosty trik:

this.paginator._changePageSize(this.paginator.pageSize); 

ten aktualizuje rozmiar strony do bieżącego rozmiaru strony, więc w zasadzie nic się nie zmienia, z wyjątkiem prywatnych _emitPageEvent() funkcji nazywa się też triggeing stołowego reload.

+0

prawdopodobnie działa, ale wydaje się być hacky ... – ConquerorsHaki

+0

Próbowałem twojego kodu i to nie działa (nie ma efektu). Jednak nextPage, a następnie poprzednia strona ponownie działają, ale nie jest rozwiązaniem. – ConquerorsHaki

3

Najlepszym sposobem na zrobienie tego jest dodanie dodatkowego obserwowalnego do implementacji Datasource.

W metodzie connect powinieneś już używać Observable.merge, aby zasubskrybować tablicę obserwowalnych, które zawierają paginator.page, sort.sortChange, itp. Możesz dodać nowy temat do tego i wywołać go obok, gdy potrzebujesz spowodować odświeżenie.

coś takiego:

export class LanguageDataSource extends DataSource<any> { 

    recordChange$ = new Subject(); 

    constructor(private languages) { 
     super(); 
    } 

    connect(): Observable<any> { 

     const changes = [ 
     this.recordChange$ 
     ]; 

     return Observable.merge(...changes) 
     .switchMap(() => return Observable.of(this.languages)); 
    } 

    disconnect() { 
     // No-op 
    } 
} 

a następnie można nazwać recordChange$.next() zainicjować odświeżania.

Naturalnie chciałbym opakować wywołanie metodą refresh() i wywołać go z instancji źródła danych w/w komponencie i inne odpowiednie techniki.

0

this.dataSource = new MatTableDataSource (this.elements);

Dodaj tę linię poniżej czynności dodawania lub usuwania danego wiersza.

refresh() { 
    this.authService.getAuthenticatedUser().subscribe((res) => { 
    this.user = new MatTableDataSource<Element>(res); 
}); 
}