Переключение между информацией о карте

У меня есть дочерний компонент, который отображает информацию при нажатии на его кнопку.

информация-data.comComponent.html

<div class = "col-12 col-sm-12 col-md-12 col-lg-12">
  <div class = "col-sm-12 col-md-12 col-lg-12 p-2 info">
    <h6  (click) = "questionClick()">{{headName}}
      <fa-icon [icon] = "icons.faInfoCircle" class = "fa-1x text-primary" transform = "shrink-2"></fa-icon>
    </h6>

  </div>
  <ng-template #childTemplate>
  <div class = "row" [hidden] = "visibleStatus">
    <div class = "col-12 bulb-section">
      <div class = "row m-0">
        <div class = "icon-bulb col">
      <p class = "ml-4">
        {{infoData}}
      </p>
        </div>
      </div>
    </div>
  </div>
  </ng-template>
  <ng-container *ngIf = "!displayInfo; then childTemplate"></ng-container>
</div>

информация-data.comComponent.ts

export class InformationDataComponent {

  @ViewChild('childTemplate', { static: true }) childTemplate: TemplateRef<any>;

  constructor() { }
  @Input() infoData: string;
  @Input() visibleStatus: boolean;
  @Input() headName: string;
  @Input() displayInfo?: boolean;

  questionClick () {
          this.visibleStatus = !this.visibleStatus;
}
}

Сценарий. В моем родительском компоненте у меня есть 3 загрузочные карты, каждая из которых имеет разные данные. Когда я нажимаю на карту, я хочу, чтобы отображалась только информация для соответствующей карты, скрывая две другие в этом сценарии.

<div class = "card">
                <div class = "card-body">
                  <information-data [infoData] = "salonInfo"
                                               [headName] = "salonHead"
                                               [visibleStatus] = "true"
                                               [displayInfo] = "true"
                  ></information-data>
                </div>
              </div>
            </div>
            <div class = "col-4 col-sm-4 col-md-4 col-lg-4">
              <div class = "card">
                <div class = "card-body">
                  <information-data [infoData] = "hospitalInfo"
                                               [headName] = "hospitalHead"
                                               [visibleStatus] = "true"
                                               [displayInfo] = "true"
                  ></information-data>
                </div>
              </div>
            </div>
            <div class = "col-4 col-sm-4 col-md-4 col-lg-4">
              <div class = "card">
                <div class = "card-body">
                  <information-data [infoData] = "travelInfo"
                                               [headName] = "travelHead"
                                               [visibleStatus] = "true"
                                               [displayInfo] = "true"
                  ></information-data>
                </div>
              </div>
        <div class = "row pl-5 pr-5">
           <ng-container *ngTemplateOutlet = "childComponent.childTemplate"></ng-container>
        </div>
</div>

Другие сценарии. Я широко использую этот дочерний компонент в других частях приложения, как показано ниже, и его не следует менять.

            <retail-information-data [infoData] = "funcInfo"
                              [headName] = "funcHead"
                              [visibleStatus] = "funcVisibility"
             ></retail-information-data>

Как я могу реализовать эту функциональность, не затрагивая другие части кода?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
52
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Используйте вывод

@Output() displayInfoChange:EventEmitter<boolean>=new EventEmitter<boolean>()

И когда изменится

   questionClick () {
       this.visibleStatus = !this.visibleStatus;
       //
       this.displayInfoChange.emit(this.visibleStatus);
   }

Итак, вы можете использовать два способа привязки, и ваш родительский элемент учтет изменение и определит массив displayInfos.

displayInfos:boolean[]=[true,false,false]

<!--change each "0", by "1" and "2" to the second and third card-->
<information-data [infoData] = "salonInfo"
                  [headName] = "salonHead"
                  [visibleStatus] = "true"
                  [(displayInfo)] = "displayInfos[0]"
                  (displayInfoChange) = "displayInfos[0] && restToFalse(0)"

                  ></information-data>


    restToFalse(index:number)
      this.displayInfos=this.displayInfos.map((x,i)=>(i==index))
    }
Ответ принят как подходящий

Мы можем использовать EventEmitter и @Output для вызова родительского кода, в котором будет храниться индекс элемента, на который был нажата кнопка, затем мы можем использовать ViewChildren, чтобы получить все присутствующие дочерние компоненты, а затем использовать установленный индекс для доступа к шаблону. .

Я также использую *ngFor as syntax для доступа к шаблону дочернего компонента!


РЕБЕНОК ТС

import { CommonModule } from '@angular/common';
import {
  Component,
  Input,
  ViewChild,
  TemplateRef,
  Output,
  EventEmitter,
} from '@angular/core';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons';

@Component({
  selector: 'information-data',
  standalone: true,
  imports: [CommonModule, FontAwesomeModule],
  templateUrl: './child.component.html',
  styleUrl: './child.component.css',
})
export class ChildComponent {
  @ViewChild('childTemplate', { static: true })
  childTemplate!: TemplateRef<any>;
  icons = {
    faInfoCircle,
  };
  constructor() {}
  @Input() infoData!: string;
  @Input() visibleStatus!: boolean;
  @Input() headName!: string;
  @Input() displayInfo?: boolean;
  @Output() clickEvent: EventEmitter<void> = new EventEmitter<void>();

  questionClick() {
    this.visibleStatus = !this.visibleStatus;
    this.clickEvent.emit();
  }
}

ДЕТСКИЙ HTML

<div class = "col-12 col-sm-12 col-md-12 col-lg-12">
  <div class = "col-sm-12 col-md-12 col-lg-12 p-2 info">
    <h6 (click) = "questionClick()">
      {{ headName }}
      <fa-icon
        [icon] = "icons.faInfoCircle"
        class = "fa-1x text-primary"
        transform = "shrink-2"
      ></fa-icon>
    </h6>
  </div>
  <ng-template #childTemplate>
    <div class = "row" [hidden] = "visibleStatus">
      <div class = "col-12 bulb-section">
        <div class = "row m-0">
          <div class = "icon-bulb col">
            <p class = "ml-4">
              {{ infoData }}
            </p>
          </div>
        </div>
      </div>
    </div>
  </ng-template>
  <ng-container *ngIf = "!displayInfo; then childTemplate"></ng-container>
</div>

ГЛАВНЫЙ.TS

import { CommonModule } from '@angular/common';
import { Component, QueryList, ViewChild, ViewChildren, ChangeDetectorRef, } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';
import { ChildComponent } from './app/child/child.component';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, ChildComponent],
  template: `
            <div class = "card">
              <div class = "card-body">
                <information-data 
                  [infoData] = "salonInfo"
                  [headName] = "salonHead"
                  [visibleStatus] = "true"
                  [displayInfo] = "true"
                  (clickEvent) = "index = 0;"
                ></information-data>
              </div>
            </div>
            <div class = "col-4 col-sm-4 col-md-4 col-lg-4">
              <div class = "card">
                <div class = "card-body">
                  <information-data 
                    [infoData] = "hospitalInfo"
                    [headName] = "hospitalHead"
                    [visibleStatus] = "true"
                    [displayInfo] = "true"
                    (clickEvent) = "index = 1;"
                  ></information-data>
                </div>
              </div>
            </div>
            <div class = "col-4 col-sm-4 col-md-4 col-lg-4">
              <div class = "card">
                <div class = "card-body">
                  <information-data 
                    [infoData] = "travelInfo"
                    [headName] = "travelHead"
                    [visibleStatus] = "true"
                    [displayInfo] = "true"
                    (clickEvent) = "index = 2;"
                  ></information-data>
                </div>
              </div>
            </div>
            <div class = "row pl-5 pr-5" *ngIf = "getChild() as child">
              <ng-container *ngTemplateOutlet = "child"></ng-container>
            </div>
  `,
})
export class App {
  @ViewChildren(ChildComponent) childComponents!: QueryList<ChildComponent>;
  name = 'Angular';
  travelHead = '12asdf3';
  travelInfo = '12asdf3';
  index = 0;
  hospitalInfo = '12asdfasdf3';
  hospitalHead = '12asdfasdf3';
  salonHead = '12zxcvxcvz3';
  salonInfo = '12zxcvxcvz3';

  constructor(private cdr: ChangeDetectorRef) {}

  ngAfterViewInit() {
    this.cdr.detectChanges();
  }

  getChild() {
    return this.childComponents?.get(this.index)?.childTemplate;
  }
}

bootstrapApplication(App);

Демо-версия Stackblitz

ExpressionChangedAfterItHasBeenCheckedError: выражение изменилось после проверки. Предыдущее значение: «не определено». Текущее значение: '[объект объекта]'. Он работает должным образом, но я получаю эту ошибку

moonchild_ 30.04.2024 11:55

@moonchild_ в main.ts также добавьте это constructor(private cdr: ChangeDetectorRef) {} ngAfterViewInit() { this.cdr.detectChanges(); }stackblitz

Naren Murali 30.04.2024 12:05

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