Я использую angular 6, и у меня есть ngbCarousel, на который я хочу добавлять фотографии одним нажатием кнопки.
Я использую ngFor
для создания HTML-кода карусели.
<ngb-carousel #carousel *ngIf = "images">
<ng-template ngbSlide *ngFor = "let im of images; let i = index">
<img [src]='im.link' >
<div>
<input type = "text" value = {{im.name}} >
<input type = "text" value='description of img' >
<input type = "text" value='copyright owners' >
<button type = "button" (click)='deletepic(i)'>delete</button>
</div>
</ng-template>
</ngb-carousel>
<button type = "button" (click)='addpic()'>add</button>
<button type = "button" (click)='last()'>last</button>
Массив images
, содержащий JSON, является этим images= [{'link':'https://picsum.photos/900/500/?image=5','name':'first'},{'link':'https://picsum.photos/900/500/?image=574','name':'second'},{'link':'https://picsum.photos/900/500/?image=547','name':'third'}];
, и при щелчке по addpic
в массив добавляется еще один json.
addpic(){
this.images.push({'link':'https://picsum.photos/900/500/?image=7','name':'added one'});
this.last() ;
}
Также он должен заставить карусель показывать последнюю, недавно добавленную фотографию. Согласно API, я должен использовать select
для перехода к слайду по его идентификатору, а идентификатор имеет шаблон ngb-slide-0
.
Итак, last
содержит
last(){
let slide = 'ngb-slide-'+String(this.images.length-1);
this.carousel.select(slide);
}
Последняя фотография обычно добавляется в карусель
Эта проблема заключается в том, что last
не будет работать при вызове с addpic
. Он никогда не переходит к последней фотографии, даже если фотография добавлена. Если я поставлю
let slide = 'ngb-slide-'+String(this.images.length-1);
this.carousel.select(slide);
last
в addpic
по-прежнему работать не будет. Он всегда переходит к предпоследней фотографии (если у меня 3 фотографии, он всегда переходит к третьей после добавления четвертой)
Но это буду работать, если я нажму последнюю кнопку или использую стрелки в пользовательском интерфейсе карусели.
Это заставляет меня думать, что каким-то образом HTML или массив не «обновляются» при вызове last
в машинописном тексте, но каким-то образом кнопки обновляют / создают HTML-код, необходимый для отображения правильной фотографии?
Я не знаю, что это такое, но теперь я почти уверен, что это связано с обновлением html / typescript. Я думаю, что это угловая проблема, а не проблема ngbCarousel. Я не знаю, как отлаживать или продолжать.
Пожалуйста посоветуй. Спасибо
После добавления изображения в массив в методе addpic () им требуется немного времени для отражения в html в качестве шаблона, поэтому вызовите последний метод по истечении времени ожидания, например
addpic(){
this.images.push({'link':'https://picsum.photos/900/500/?image=7','name':'added one'});
setTimeout(() => {
this.last();
});
}
Вы можете использовать setTimeout
для принудительного выполнения метода last
после того, как изменения были обнаружены Angular, как в ответе Пареша Гамиса.
Но я думаю, что вы также могли бы использовать ChangeDetectorRef.detectChanges()
в этой ситуации, он кажется менее "хакерским". (Документация и связанные вопросы и ответы здесь: В чем разница между markForCheck () и detectChanges ())
используйте его непосредственно перед вызовом last
.
Я не уверен, сработает ли это в вашем случае (если вы предоставите минимальный пример StackBlitz, мы могли бы поработать над деталями)
setTimeout
великолепен, но иногда дает вспышку пустой карусели. О detectChanges
: звучит круто, но я новичок в Angular и понятия не имею, что делать. В чем логика? Определить, был ли изменен HTML ngb-carousel
, а затем вызвать last
? Не могли бы вы рассказать подробнее, и я создам фондовый рынок или как вы, ребята, сейчас это называете. Шучу, я устанавливаю StackBlitz
Извините, я не понимаю, что это пустое поле, я импортировал ng-bootstrap, bootstrap.css
и необходимый импорт в компонент. «Это работает в моей машине». Я пытаюсь разобраться, что не так stackBlitz
@selvin есть две ошибки, которые я могу исправить (и теперь я вижу ваш пример). Во-первых, есть строка импорта, которую вам нужно удалить в компоненте (MapcmsService), и вам нужно добавить ReactiveFormsModule в импорт app.module.ts
Теперь я застрял, я не могу добавлять фотографии (кажется, stackblitz не любит picsum.photos? Или это моя сетевая корпорация сейчас возится с HTTPS?)
в принципе, я просто хотел попробовать this.changeDetectorRef.detectChanges(); this.last();
вместо setTimeout(() => { this.last(); });
У меня плохие новости. Когда вы удаляете фотографию, а затем добавляете новую, я думаю, идентификаторы ngb-slide-XX
сбиваются, и я снова оказываюсь на предпоследней фотографии !!!! Это выходит из под контроля. Есть ли способ просто показать последнее фото? Что меня расстраивает, так это то, что у меня есть простой массив, и я не могу заставить angular просто перейти к его концу и каким-то образом отобразить то, что находится внутри. Я не могу сейчас ни о чем думать, если у вас есть совет, это было бы здорово. В противном случае я не знаю. Думаю, я открою вопрос о ng-bootstrap
. У меня нет времени на создание собственной галереи ...
Извините за волнение, решение есть. Я могу выполнить угловой обход тега ng-template ngbSlide
, получить последний тег, получить его идентификатор и использовать его на this.carousel.select(actually_last_slide);
. Работая над ним.
Итак, все сводится к проблеме цикла событий JS.
setTimeout
- это грязный хакер, и я люблю его, как и все грязные хаки :) Проблема в том, что при первом вызове я вижу вспышку пустогоdiv
без изображения внутри.