Угловое обновление значений в представлениях

У меня есть приложение 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>

ваше приложение stackblitz, похоже, не работает с Error occurred: Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript.

chris 10.05.2022 15:19
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут...
0
1
41
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы правы, пытаясь использовать 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!

Удачи, дайте мне знать, если это не ясно!

Большой! Спасибо! Я попробую и дам вам знать.

markbernard 10.05.2022 15:39

Разрешать прямой доступ к BehaviorSubject считается плохой практикой. Вы должны написать геттер, который выставляет объект как Observable.

ak.leimrey 10.05.2022 16:05
Ответ принят как подходящий

Один из способов обмена данными между компонентами — использование 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/…

ak.leimrey 10.05.2022 16:09

да, это лучшая практика. я обновил сервис

chris 10.05.2022 16:23

Другие вопросы по теме