Angular 跨视图更新值

Angular updating values across views

我有一个 Angular 应用程序,其中包含以下内容: 一个组件有一个文本输入和一个按钮。用户填写文本输入并单击按钮。这会为路由器 link.

更新 URL

路由器 link 加载一个名为 view 的组件,它依次从路由器 link 读取 URL 参数并将该值放在服务中并显示在组件上所以我知道它有效。

因此,如果用户在文本输入中键入 'abc',则路由器 link URL 将是 /view/abc。因此 'abc' 将显示在视图组件中。有时用户会像/view/def一样粘贴路由器link。这适用于更新视图组件。

我无法开始工作的部分是更新另一个组件中的文本输入框以反映粘贴的当前值 link。

我尝试使用 'AfterViewChecked' 从服务中读取值,但它在服务值更新之前执行,所以它总是不正确。

这些不能绑定到同一个变量,因为这最终会变成网络服务调用,我不希望在用户在文本输入框中键入内容时仅在他们单击按钮时更新服务.

我不确定还有什么地方可以看。我所做的任何搜索都会带来数据绑定,但这不是我的问题。

相关文件如下,但完整的测试示例代码位于 https://stackblitz.com/edit/github-jwr6wj.

的 StackBlitz 上

如果您更改文本输入中的 URL 并单击按钮,下面的 URL 显示将更新。但是,如果您粘贴伪 URL https://github-jwr6wj.stackblitz.io/view/http%253A%252F%252Fwww.ebay.com%252F,下面显示的 URL 将正确更新,但我不知道如何更新文本输入以反映 URL.

update.service.ts 包含当前的 URL。此服务还将从 Web 服务加载数据。

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>

toolbar.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);
  }
}

toolbar.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 是正确的,因为这只是一个时间问题。您可以做的是在 updateService 中将 url 定义为 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内部订阅Behavior Subject)

<p>URL: {{updateService.url$ | async}}</p>

而且您还必须处理 url 是工具栏组件 ts!

中的主题这一事实

祝你好运,如果不清楚请告诉我!

在组件之间共享数据的一种方法是使用服务和 Observables。将服务中的 url 更改为具有初始值的 BehaviorSubject

BehaviorSubject 的工作方式是您从组件发出值以更新服务中的 Observable。 BehaviorSubject 既作为 Observer 又作为 Observable。

本质上,Observer 是一个监听事件的对象,在这种情况下,更新 URL。 Observable 是组件侦听更新或更改的对象。在这种情况下,视图组件监听 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>