У меня была такая же проблема, я использую AfterViewChecked
и @ViewChild
комбинированную (Angular2 beta.3).
Компонент:
import {..., AfterViewChecked, ElementRef, ViewChild, OnInit} from 'angular2/core'
@Component({
...
})
export class ChannelComponent implements OnInit, AfterViewChecked {
@ViewChild('scrollMe') private myScrollContainer: ElementRef;
ngOnInit() {
this.scrollToBottom();
}
ngAfterViewChecked() {
this.scrollToBottom();
}
scrollToBottom(): void {
try {
this.myScrollContainer.nativeElement.scrollTop = this.myScrollContainer.nativeElement.scrollHeight;
} catch(err) { }
}
}
Шаблон:
<div #scrollMe style="overflow: scroll; height: xyz;">
<div class="..."
*ngFor="..."
...>
</div>
</div>
Конечно, это довольно просто. AfterViewChecked
Срабатывает каждый раз , когда проверялся вид:
Реализуйте этот интерфейс, чтобы получать уведомления после каждой проверки представления вашего компонента.
Если у вас есть поле ввода для отправки сообщений, например, это событие запускается после каждого нажатия клавиши (просто для примера). Но если вы сохраните, прокручивает ли пользователь вручную, а затем пропустите, scrollToBottom()
все будет в порядке.
позвольте мне просто исправить это
источник
Самое простое и лучшее решение для этого:
Добавьте эту
#scrollMe [scrollTop]="scrollMe.scrollHeight"
простую вещь на стороне шаблонаВот ссылка на РАБОЧУЮ ДЕМО (с фиктивным приложением чата) И ПОЛНЫЙ КОД
источник
Expression has changed after it was checked. Previous value: 'scrollTop: 1758'. Current value: 'scrollTop: 1734'
. Вы это решили?Я добавил проверку, пытался ли пользователь прокрутить вверх.
Я просто оставлю это здесь, если кому-то это нужно :)
и код:
источник
Принятый ответ срабатывает при прокрутке сообщений, это позволяет избежать этого.
Вам нужен такой шаблон.
Затем вы хотите использовать аннотацию ViewChildren для подписки на новые элементы сообщения, добавляемые на страницу.
источник
Рассмотрите возможность использования
См. Https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView.
источник
Если вы хотите быть уверенным, что прокручиваете до конца после завершения * ngFor, вы можете использовать это.
Важно здесь, что «последние» переменная определяет , если вы в настоящее время последний пункт, так что вы можете вызвать «scrollToBottom» метод
источник
источник
Делюсь своим решением, потому что остальное меня не полностью устраивало. Моя проблема в
AfterViewChecked
том, что иногда я прокручиваю вверх, и по какой-то причине вызывается этот жизненный крючок, и он прокручивает меня вниз, даже если не было новых сообщений. Я пробовал использовать,OnChanges
но это была проблема, которая привела меня к этому решению. К сожалению, при использовании onlyDoCheck
он прокручивался вниз до того, как сообщения были отображены, что тоже было бесполезно, поэтому я объединил их, так что DoCheck в основном указывает,AfterViewChecked
должен ли он вызыватьscrollToBottom
.Рады получать отзывы.
chat.component.html
chat.component.sass
источник
const isScrolledDown = Math.abs(this.scrollable.nativeElement.scrollHeight - this.scrollable.nativeElement.scrollTop - this.scrollable.nativeElement.clientHeight) <= 3.0;
(где 3.0 - допуск в пикселях). Его можно использовать,ngDoCheck
чтобы условно не задаватьshouldScrollDown
значение,true
если пользователь прокручивается вручную.ngAfterViewChecked
с другим логическим значением. Я изменилshouldScrollDown
имя на,numberOfMessagesChanged
чтобыif (this.numberOfMessagesChanged && !isScrolledDown)
, что вы понимаете, но я думаю, вы не поняли смысла моего предложения. Мое реальное намерение - не прокручивать автоматически вниз, даже когда добавляется новое сообщение, если пользователь вручную прокручивает вверх. Без этого, если вы прокрутите вверх, чтобы увидеть историю, чат будет прокручиваться вниз, как только появится новое сообщение. Это может быть очень раздражающим поведением. :) Итак, я предложил проверить, прокручивается ли чат до того, как новое сообщение будет добавлено в DOM, и не использовать автопрокрутку, если это так.ngAfterViewChecked
слишком поздно, потому что DOM уже изменился.Ответ Вивека сработал для меня, но в результате выражение изменилось после того, как была проверена ошибка. Ни один из комментариев у меня не сработал, но я изменил стратегию обнаружения изменений.
источник
В angular с использованием сайднава Material Design мне пришлось использовать следующее:
источник
источник
После прочтения других решений лучшее решение, которое я могу придумать, поэтому вы запускаете только то, что вам нужно, следующее: вы используете ngOnChanges для обнаружения правильного изменения
И вы используете ngAfterViewChecked, чтобы фактически применить изменение до его рендеринга, но после вычисления полной высоты
Если вам интересно, как реализовать scrollToBottom
источник