Плагин Angular 5 и JQuery перезаписывает DOM - PullRequest
0 голосов
/ 16 октября 2018

Я интегрирую плагин jQuery в Angular и у меня возникают некоторые проблемы

Plunker: https://next.plnkr.co/edit/pNCmYOo4vizJuj9V

Обратите внимание, что слайдеры слайдера отображаются правильно, а затем загрузчик plunker сначала загружается, нажмите кнопку "Переключить"поменяйте слайды и обратите внимание, что теперь слайдер окончательно сломан.

Как лучше всего решить эту проблему?

1 Ответ

0 голосов
/ 16 октября 2018
import {
  Component,
  OnInit,
  EventEmitter,
  ChangeDetectorRef,
  Input,
  ElementRef,
  AfterViewInit,
  Output,
} from '@angular/core';

export interface FlexSliderSlide {
  id: string;
  name: string;
  image: string;
}

@Component({
  selector: 'flexslider',
  template: `
    <div class="clearfix">
      <div class="clearfix" *ngIf="_slides">
        <div flexslider class="flexslider carousel">
          <ul class="slides">
            <li [ngClass]="{ selected: selectedSlide?.id === slide.id }" *ngFor="let slide of _slides" (click)="onSlideSelected(slide)">
              <div class="title">
                {{ slide.name }}
              </div>
              <div class="img">
                <img class="img-responsive" [src]="slide.image" [attr.alt]="slide.name" />
              </div>
            </li>
          </ul>
        </div>
      </div>
    </div>
  `,
  styles: [`
    .carousel {
      margin: 0;
      border: solid 1px #ccc;
      padding: 20px;
    }
    .slides > li .img {
      cursor: pointer;
      border: solid 1px #ccc;
    }
    .slides > li:hover .img {
      box-shadow: 0 0 8px rgba(0, 0, 0, .2);
    }
    .slides > li.selected .img {
      box-shadow: 0 0 8px rgba(0, 0, 0, .2);
      border: solid 2px #00ccb0;
    }
    .title {
      color: #4A4A4A;
      font-size: 17px;
      font-weight: bold;
      line-height: 16px;
      margin-bottom: 16px;
    }
    ::ng-deep .flex-control-nav.flex-control-paging {
      display: none;
    }
    ::ng-deep .flexslider ul.flex-direction-nav {
      position: static !important;
    }
    ::ng-deep .flexslider ul.flex-direction-nav a {
      width: 20px;
      height: 20px;
      margin: -10px 0 0;
    }
    ::ng-deep .flexslider ul.flex-direction-nav a:before {
      font-size: 18px;
    }
  `]
})
export class FlexSliderComponent implements AfterViewInit {
  private _slides: FlexSliderSlide[];
  // Most magic happens below...!
  @Input() set slides(v: FlexSliderSlide[]) {
    if (v && (JSON.stringify(v) !== JSON.stringify(this._slides))) {
      // ^-- Checks whether the model has somehow changed.
      console.log('triggering change');
      $(this.el.nativeElement.querySelector('.flexslider')).removeData("flexslider");
      // ^-- remove existing data...
      this._slides = v;
      this.cd.detectChanges();
      // ^-- Force a redraw..
      this.ngAfterViewInit();
      // ^ -- Reinit the jQuery element.
    }
  }
  @Output() onSelected = new EventEmitter();
  selectedSlide: FlexSliderSlide;

  constructor(
    private cd: ChangeDetectorRef,
    private el: ElementRef
  ) { }

  ngAfterViewInit(): void {
    $(this.el.nativeElement.querySelector('.flexslider')).flexslider({
      animation: 'slide',
      animationLoop: false,
      slideshow: false,
      controlNav: false,
      itemWidth: 250,
      itemMargin: 54
    });
  }

  onSlideSelected(selected: FlexSliderSlide) {
    this.selectedSlide = selected;
    this.onSelected.emit(selected);
    this.cd.detectChanges();
  }

}

По сути, это, по-видимому, связано с самим flexSlider. Подробнее об этом можно прочитать здесь: Перезагрузить Flexslider

Поскольку он не поддерживает обновление, необходимо перерисоватьвесь элемент jQuery при каждом изменении источника, поэтому вам нужно проверить, изменился ли источник.Чтобы сделать это, я просто проверил строковую проверку, вы можете реализовать более умный способ проверить, изменились ли элементы (может быть, достаточно проверок идентификатора?).Тем не менее, после замены слайдов вам нужно запустить измененное обновление обнаружения, чтобы компонент перерисовывался, затем вы можете снова вызвать ngAfterInit для повторного запуска слайдера, и это прекрасно выполнит работу.

Обновлен plnkr: https://next.plnkr.co/edit/L7yfcem2uz5UsYEO

...