typescript - Angular yönlendirilmiş bileşenlere veriyi nasıl geçerim?
Angular 2 rotalarımdan birinin şablonunda (FirstComponent) bir butonum var
first.component.html
<div class="button" click="routeWithData()">Pass data and route</div>
Benim hedefim şunları başarmaktır:
Düğmeye tıklama -> Başka bir bileşene yönlendirme, veriyi koruyarak ve diğer bileşeni direktif olarak kullanmadan.
Bunu denedim...
1. YAKLAŞIM
Aynı bakış açısıyla, kullanıcı etkileşimine dayalı olarak aynı verileri topluyor ve saklıyorum.
first.component.ts
export class FirstComponent {
constructor(private _router: Router) { }
property1: number;
property2: string;
property3: TypeXY; // this a class, not a primitive type
// here some class methods set the properties above
// DOM events
routeWithData(){
// here route
}
}
Normalde SecondComponent'e yönlendirirdim
this._router.navigate(['SecondComponent']);
nihayet veriyi ileterek
this._router.navigate(['SecondComponent', {p1: this.property1, p2: property2 }]);
parametrelerle bağlantının tanımı ise şöyle olur
@RouteConfig([
// ...
{ path: '/SecondComponent/:p1:p2', name: 'SecondComponent', component: SecondComponent}
)]
Bu yaklaşımla ilgili sorun, tahminimce karmaşık verileri (örneğin property3 gibi bir nesne) URL içinde geçiremeyeceğim.
2. YAKLAŞIM
Alternatif olarak, SecondComponent'i FirstComponent içinde directive olarak dahil etmek olurdu.
<SecondComponent [p3]="property3"></SecondComponent>
Ancak bu bileşene yönlendirmek istiyorum, dahil etmek değil!
3. YAKLAŞIM
Burada gördüğüm en uygulanabilir çözüm, bir Hizmet (ör. FirstComponentService) kullanmak olurdu
- veriyi sakla (_firstComponentService.storeData()) FirstComponent içindeki routeWithData() üzerinde
- SecondComponent içinde ngOnInit() içinde verileri (_firstComponentService.retrieveData()) al
Bu yaklaşım tamamen uygulanabilir görünse de, bunun amacı gerçekleştirmek için en kolay/en zarif yol olup olmadığını merak ediyorum.
Genel olarak, verileri bileşenler arasında geçirmek için başka potansiyel yaklaşımları kaçırıp kaçırmadığımı bilmek isterim, özellikle de mümkün olan en az kod miktarıyla
Cevap #1
Güncelleme 4.0.0
Daha fazla ayrıntı için Angular Angular Yönlendirici - Gezinmeden önce veri alma kısmına bakın.
Orijinal
Bir servis kullanmak doğru yoldur. Rota parametrelerinde sadece tarayıcı URL çubuğunda görünmesini istediğiniz verileri geçmelisiniz.
Angular Angular Yemek Kitabı Bileşen İletişimi - Çift Yönlü Servisine Bakın.
RC.4 ile gönderilen yönlendirici data öğesini yeniden tanıtıyor
constructor(private route: ActivatedRoute) {}
const routes: RouterConfig = [
{path: '', redirectTo: '/heroes', pathMatch: 'full'},
{path: 'heroes', component: HeroDetailComponent, data: {some_data: 'some value'}}
];
class HeroDetailComponent {
ngOnInit() {
this.sub = this.route
.data
.subscribe(v => console.log(v));
}
ngOnDestroy() {
this.sub.unsubscribe();
}
}
Ayrıca Plunker'a bakın.
Cevap #2
Angular 7.2.0, yönlendirilmiş bileşenler arasında gezinirken veriyi aktarmanın yeni bir yolunu tanıttı:
@Component({
template: `<a (click)="navigateWithState()">Go</a>`,
})
export class AppComponent {
constructor(public router: Router) {}
navigateWithState() {
this.router.navigateByUrl('/123', { state: { hello: 'world' } });
}
}
Veya :
@Component({
selector: 'my-app',
template: `
<a routerLink="/details" [state]="{ hello: 'world' }">Go</a>`,
})
export class AppComponent {}
Durumu okumak için, gezinme tamamlandıktan sonra window.history.state özelliğine erişebilirsiniz:
export class PageComponent implements OnInit {
state$: Observable<object>;
constructor(public activatedRoute: ActivatedRoute) {}
ngOnInit() {
this.state$ = this.activatedRoute.paramMap
.pipe(map(() => window.history.state))
}
}
Cevap #3
Bence Angular 1.x'teki gibi $rootScope gibi bir şeye Angular 2'de sahip olmadığımız için, Angular 2 paylaşılan servis/sınıfını kullanabiliriz ve ngOnDestroy sırasında veriyi servise geçirebilir ve yönlendirmeden sonra ngOnInit fonksiyonunda servisten veriyi alabiliriz:
Burada kahraman nesnesini paylaşmak için DataService kullanıyorum:
import { Hero } from './hero';
export class DataService {
public hero: Hero;
}
İlk sayfa bileşeninden nesneyi geçirin:
ngOnDestroy() {
this.dataService.hero = this.hero;
}
İkinci sayfa bileşeninden nesneyi al:
ngOnInit() {
this.hero = this.dataService.hero;
}
İşte bir örnek: plunker
Cevap #4
<div class="button" click="routeWithData()">Pass data and route</div>
Angular 6'da veya diğer sürümlerde bunu yapmanın en kolay yolu, umarım, geçirmek istediğiniz veri miktarıyla yolunuzu basitçe tanımlamaktır.
{path: 'detailView/:id', component: DetailedViewComponent}
Rota tanımımda görebileceğiniz gibi, bileşene router navigasyonu ile geçmek istediğim verilere karşılık gelmesi için /:id ekledim. Bu nedenle kodunuz şöyle görünecek
<a class="btn btn-white-view" [routerLink]="[ '/detailView',list.id]">view</a>
Bileşendeki id'yi okumak için, sadece ActivatedRoute'u şu şekilde içe aktarın
import { ActivatedRoute } from '@angular/router'
ve verileri aldığınız yer ngOnInit'dir
ngOnInit() {
this.sub = this.route.params.subscribe(params => {
this.id = params['id'];
});
console.log(this.id);
}
bu makalede daha fazla okuyabilirsiniz https://www.tektutorialshub.com/angular-passing-parameters-to-route/
Cevap #5
Bu sayfadaki her çözümü inceledim (ve birkaçını denedim) ama veri aktarımını route arasında gerçekleştirmek için bir tür geçici çözüm uygulamamız gerektiğine ikna olmadım.
Basit history.state ile ilgili bir diğer problem, eğer state nesnesinde belirli bir sınıfın bir örneğini geçiriyorsanız, onu alırken artık o örnek olmayacaktır. Bunun yerine basit bir JavaScript nesnesi olacaktır.
Yani benim Angular v10 (Ionic v5) uygulamamda, bunu yaptım-
this.router.navigateByUrl('/authenticate/username', {
state: {user: new User(), foo: 'bar'}
});
Ve gezinme bileşeninde ('/authenticate/username'), ngOnInit() metodunda verileri this.router.getCurrentNavigation().extras.state ile yazdırdım-
ngOnInit() {
console.log('>>authenticate-username:41:',
this.router.getCurrentNavigation().extras.state);
}
Ve aktarılan istenen veriyi aldım.
Cevap #6
2019 ve burada verilen birçok cevap işe yarayabilir, ne yapmak istediğinize bağlı olarak. Eğer URL'de görünmeyen bazı dahili durumları (params, query) geçirmek istiyorsanız, 7.2'den beri state kullanabilirsiniz (bunu bugün öğrendim :) ).
Blogdan (teşekkürler Tomasz Kula) - rotaya gidiyorsunuz....
...ts'ten: this.router.navigateByUrl('/details', { state: { hello: 'world' } });
...HTML şablonundan: <a routerLink="/details" [state]="{ hello: 'world' }">Git</a>
Ve hedef bileşende onu almak için:
constructor(public activatedRoute: ActivatedRoute) {}
ngOnInit() {
this.state$ = this.activatedRoute.paramMap
.pipe(map(() => window.history.state))
}
Geç oldu ama umarım bu, yakın zamanda Angular kullanan birine yardımcı olur.
Cevap #7
Bu sorun için diğer yaklaşım iyi değil. Bence en iyi yaklaşım, iki yolu olan Query-Parameter kullanılarak Router Angular'dır:
Sorgu parametresini doğrudan geçirme
Bu kod ile HTML kodunuzda params yardımıyla url'ye gidebilirsiniz:
<a [routerLink]="['customer-service']" [queryParams]="{ serviceId: 99 }"></a>
Routerile sorgu parametresi geçirme
Router'ı constructor içinde şöyle enjekte etmelisiniz:
constructor(private router:Router){
}
Şimdi bunun kullanımı şöyle:
goToPage(pageNum) {
this.router.navigate(['/product-list'], { queryParams: { serviceId: serviceId} });
}
Şimdi eğer başka bir Component'te Router'dan okumak istiyorsanız, şu şekilde ActivatedRoute kullanmanız gerekir:
constructor(private activateRouter:ActivatedRouter){
}
ve subscribe şunu:
ngOnInit() {
this.sub = this.route
.queryParams
.subscribe(params => {
// Defaults to 0 if no query param provided.
this.page = +params['serviceId'] || 0;
});
}
Cevap #8
Ben olmayan bazı süper zeki bir kişi (tmburnell), rota verilerini yeniden yazmayı öneriyor:
let route = this.router.config.find(r => r.path === '/path');
route.data = { entity: 'entity' };
this.router.navigateByUrl('/path');
Bunu yorumlarda görüldüğü gibi.
Umarım biri bunu faydalı bulur
Cevap #9
ActiveRoute ile çözüm (eğer nesneyi rota ile geçirmek istiyorsanız - JSON.stringify/JSON.parse kullanın):
Göndermeden önce nesneyi hazırlayın:
export class AdminUserListComponent {
users : User[];
constructor( private router : Router) { }
modifyUser(i) {
let navigationExtras: NavigationExtras = {
queryParams: {
"user": JSON.stringify(this.users[i])
}
};
this.router.navigate(["admin/user/edit"], navigationExtras);
}
}
Nesnenizi hedef bileşende alın:
export class AdminUserEditComponent {
userWithRole: UserWithRole;
constructor( private route: ActivatedRoute) {}
ngOnInit(): void {
super.ngOnInit();
this.route.queryParams.subscribe(params => {
this.userWithRole.user = JSON.parse(params["user"]);
});
}
}
Cevap #10
Rotalar :
{ path: 'foo-route', component: FooComponent, data: { myData: false } },
Bileşende veriye bir kez erişin:
pipe(take(1)) hemen aboneliği iptal eder, bu nedenle bellek sızıntısı olmaz ve manuel olarak aboneliği iptal etmeye gerek yoktur
constructor(private activatedRoute: ActivatedRoute) { ... }
ngOnInit(): void {
this.activatedRoute.data.pipe(take(1)).subscribe((data) => {
console.log(data); // do something with the data
});
}
- gerekli şeyleri içe aktarmayı unutma
Düzenle: yeni firstValueFrom() daha iyi olabilir


