У меня есть приложение Angular со следующим: Один компонент имеет ввод текста и кнопку. Пользователь вводит текст и нажимает кнопку. Это обновляет URL-адрес для ссылки на маршрутизатор.
Ссылка на маршрутизатор загружает компонент с именем view, который, в свою очередь, считывает параметр URL из ссылки на маршрутизатор, помещает это значение в службу и отображает его в компоненте, поэтому я знаю, что это сработало.
Таким образом, если пользователь введет «abc» в текстовый ввод, тогда URL-адрес ссылки маршрутизатора будет /view/abc. Таким образом, «abc» будет отображаться в компоненте представления. Иногда пользователи вставляют ссылку на маршрутизатор, например /view/def. Это работает для обновления компонента представления.
Часть, которую я не могу приступить к работе, - это обновить поле ввода текста в другом компоненте, чтобы отразить текущее значение вставленной ссылки.
Я попытался использовать «AfterViewChecked», чтобы прочитать значение из службы, но оно выполняется до того, как значение службы будет обновлено, поэтому оно всегда неверно.
Они не могут привязываться к одной и той же переменной, потому что это в конечном итоге превратится в вызов веб-службы, и я не хочу, чтобы служба обновлялась, пока пользователь вводит текст в поле ввода, только когда они нажимают кнопку.
Я не уверен, где еще искать. Любой поиск, который я делаю, просто вызывает привязку данных, но это не моя проблема.
Соответствующие файлы находятся ниже, но полный тестовый пример кода находится на StackBlitz по адресу https://stackblitz.com/edit/github-jwr6wj.
Если вы измените URL-адрес в текстовом поле и нажмете кнопку, отображаемый ниже URL-адрес обновится. Но если вы вставите псевдо-URL-адрес https://github-jwr6wj.stackblitz.io/view/http%253A%252F%252Fwww.ebay.com%252F, URL-адрес, отображаемый ниже, будет обновлен правильно, но я не могу понять, как обновить текстовый ввод, чтобы отразить то, что пришло с URL-адресом.
update.service.ts содержит текущий URL-адрес. Эта служба также будет загружать данные из веб-службы.
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class UpdateService {
url: string = "http://www.google.com/";
constructor() { }
}
view.component.ts — это место, где будут отображаться данные, выбранные пользователем. Он анализирует параметр URL для данных и обновляет службу с его помощью.
import { ActivatedRoute, ParamMap } from '@angular/router';
import { UpdateService } from '../update.service';
@Component({
selector: 'app-view',
templateUrl: './view.component.html',
styleUrls: ['./view.component.css']
})
export class ViewComponent implements OnInit {
constructor(public activatedRoute:ActivatedRoute, public updateService: UpdateService) { }
ngOnInit(): void {
this.activatedRoute.paramMap.subscribe((paramMap: ParamMap) =>{
this.getUrl(paramMap);
});
}
getUrl(paramMap: ParamMap): void {
const incomingUrl = paramMap.get("url");
if (incomingUrl == null) {
this.updateService.url = "http://www.google.com/";
} else {
this.updateService.url = decodeURIComponent(incomingUrl);
}
}
}
view.component.html
<p>URL: {{updateService.url}}</p>
панель инструментов.component.ts — это место, где пользователь будет вводить свой запрос. sourceUrl — это переменная, которая будет обновляться при вводе пользователем. Однако я также хочу, чтобы он обновлялся при посещении страницы через URL-адрес браузера с правильными данными как часть этого URL-адреса. Я могу отправлять данные в компонент представления через маршрутизатор, но не могу понять, как отправить данные обратно в компонент панели инструментов.
import { UpdateService } from '../update.service';
@Component({
selector: 'app-toolbar',
templateUrl: './toolbar.component.html',
styleUrls: ['./toolbar.component.css'],
})
export class ToolbarComponent implements OnInit {
sourceUrl: string = '';
constructor(private updateService: UpdateService) {}
ngOnInit(): void {
this.sourceUrl = this.updateService.url;
}
getViewUrl(): string {
return '/view/' + encodeURIComponent(this.sourceUrl);
}
}
панель инструментов.component.html
<div class = "col-sm-12">
<input type = "text" [(ngModel)] = "sourceUrl" />
<a class = "btn btn-primary" [routerLink] = "getViewUrl()">
<span class = "fa fa-eye"></span>
</a>
</div>






Вы правы, пытаясь использовать AfterViewChecked, потому что это просто вопрос времени. Что вы могли бы сделать, так это определить url внутри updateService как BehaviourSubject, чтобы в момент его обновления в вашем компоненте представления вы видели изменение в компоненте панели инструментов.
Внутри сервиса:
public url$: BehaviorSubject<string> = new BehaviorSubject("http://www.google.com/");
Внутри компонента представления ts :
getUrl(paramMap: ParamMap): void {
const incomingUrl = paramMap.get("url");
if (incomingUrl == null) {
this.updateService.url$.next("http://www.google.com/");
} else {
this.updateService.url$.next(decodeURIComponent(incomingUrl));
}
}
И внутри компонента представления HTML: (вы также можете подписаться на тему поведения непосредственно внутри ts)
<p>URL: {{updateService.url$ | async}}</p>
И вам также придется иметь дело с тем фактом, что URL-адрес является Темой внутри компонента панели инструментов ts!
Удачи, дайте мне знать, если это не ясно!
Большой! Спасибо! Я попробую и дам вам знать.
Разрешать прямой доступ к BehaviorSubject считается плохой практикой. Вы должны написать геттер, который выставляет объект как Observable.
Один из способов обмена данными между компонентами — использование Service и Observables. Измените свой URL-адрес в Сервисе на BehaviorSubject с начальным значением.
Принцип работы BehaviorSubject заключается в том, что вы выдаете значения из компонентов для обновления Observable в сервисе. BehaviorSubject ведет себя как Observer и Observable.
По сути, Наблюдатель — это объект, который прослушивает события, в данном случае обновляя URL-адрес. Наблюдаемый — это объект, который компоненты прослушивают для обновлений или изменений. В этом случае компонент просмотра прослушивает BehaviorSubject для этого обновления URL-адреса.
Услуга
export class UpdateService {
private url$ = new BehaviorSubject<string>('www.google.com');
public readonly url: Observable<string> = this.url$.asObservable();
constructor() {}
}
Компонент панели инструментов
export class ToolbarComponent implements OnInit {
sourceUrl: string = '';
constructor(private updateService: UpdateService) {}
ngOnInit(): void {
this.updateService.url.subscribe((str) => {
this.sourceUrl = str;
});
}
getViewUrl(): string {
return '/view/' + encodeURIComponent(this.sourceUrl);
}
}
Просмотр компонента
export class ViewComponent implements OnInit {
constructor(
public activatedRoute: ActivatedRoute,
public updateService: UpdateService
) {}
ngOnInit(): void {
this.activatedRoute.paramMap.subscribe((paramMap: ParamMap) => {
this.getUrl(paramMap);
});
}
getUrl(paramMap: ParamMap): void {
const incomingUrl = paramMap.get('url');
if (incomingUrl == null) {
this.updateService.url.next('http://www.google.com/');
} else {
this.updateService.url.next(decodeURIComponent(incomingUrl));
}
}
}
Просмотр компонента HTML
<p>URL: {{ updateService.url | async }}</p>
Служба не должна раскрывать объект BehaviorSubject. Предполагается, что его роль распространяет изменения, не позволяя пользователю иметь доступ к значениям. Вы должны выставить его через геттер как наблюдаемый. blog.angular-university.io/…
да, это лучшая практика. я обновил сервис
ваше приложение stackblitz, похоже, не работает с
Error occurred: Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.