2016-05-24 14 views
9

Ich versuche, eine Seite mit zwei Segmenten "Chat" und "Inhalt" zu kodieren. Ich möchte, dass ein "Chat" Segment die Seite automatisch nach unten ohne Effekt blättern. Der Chat ist ein <ion-list> mit mehreren <ion-item>.ionische 2 + eckige 2: auto blättern bis zum Ende der Liste/Seite/Chat

<ion-list> 
<ion-item> item 1 </ion-item> 
<ion-item> item 2 </ion-item> 
.... 
<ion-item> item 20 </ion-item> 
<ion-item> item 21 </ion-item> <!-- user should see directly this item on bottom of the page --> 
</ion-list> 

Ich benutze Javascript, nicht Typoskript, und ich möchte nicht jQuery verwenden. Danke :) Plus, wenn ich zum "Inhalt" Segment gehen und zurück zu "Chat" Ich möchte wieder automatisch den Chat-Chat.

Antwort

4

Erstens einmal ist @rinukkusu Antwort richtig, aber es funktioniert nicht auf meinem Fall arbeiten, weil <ion-content> (Eltern von <ion-list>) einige Fehler hat damit (ionische Entwickler daran arbeiten), also musste ich Setzen Sie dieses Element mit scroll:hidden und erstellen Sie einen zweiten Inhalt im Inneren, um den automatischen Bildlauf anzuwenden. Schließlich mit der rechten (s) CSS habe ich die Funktion auf construtor aufgerufen, wenn die Seite lädt und dann jedes Mal, wenn die Benutzer auf "Chat" Segment klickt.

chat.html

<!-- I create the segment and call the `autoScroll()` when users clicks on "chat" --> 
<ion-toolbar primary class="toolbar-segment"> 
    <ion-segment light [(ngModel)]="segment"> 
     <ion-segment-button value="chat" (click)="autoScroll()"> 
      Chat 
     </ion-segment-button> 
     <ion-segment-button value="profile"> 
      Profile 
     </ion-segment-button> 
    </ion-segment> 
</ion-toolbar> 

<!--I wrote the css inline just as example. 
    DON'T do it on your project D: --> 

<!-- overflow:hidden prevent the ion-content to scroll --> 
<ion-content [ngSwitch]="segment" style="overflow: hidden;"> 

    <!-- height: 100% to force scroll if the content overflows the container. 
     #chat-autoscroll is used by javascript.--> 
    <div class="content-scroll" id="chat-autoscroll" *ngSwitchWhen="'chat'" style="height: 100%; overflow: scroll"> 
     (... make sure the content is bigger 
     than the container to see the auto scroll effect ...) 
    </div> 

    <!-- here it's just a normal scroll --> 
    <div *ngSwitchWhen="'profile'" class="content-scroll" style="height: 100%; overflow: auto"> 
     (... content of profile segment ...) 
    </div> 

</ion-content> 

chat.js

constructor() { 

    // when the user opens the page, it shows the "chat" segment as initial value 
    this.segment = 'chat'; 

    // when page loads, it calls autoScroll(); 
    if (this.segment == 'chat') { 
     console.log('chat'); 
     this.autoScroll(); 
    }; 
} 

/*Here comes the tricky. 
If you don't use setTimeout, the console will say that 
#chat-autoscroll doesn't exist in the first call (inside constructor). 
This happens because the script runs before the DOM is ready. 
I did a workaround with a timeOut of 10ms. 
It's enough time to DOM loads and then autoScroll() works fine. 
*/ 
autoScroll() { 
    setTimeout(function() { 
     var itemList = document.getElementById("chat-autoscroll"); 
     itemList.scrollTop = itemList.scrollHeight; 
    }, 10); 
} 

Fazit: Die Funktion zweimal aufgerufen wird. Wenn die Seite geladen wird (Konstruktor) und jedes Mal, wenn der Benutzer zum "Chat" -Segment zurückkehrt. (klick) = "autoScroll()"

Ich hoffe das hilft jemandem. Wenn Sie es besser wissen, lassen Sie es mich wissen! Ich habe vor ein paar Wochen angefangen, mit Angular2 und Ionic2 zu spielen, also gibt es viele Konzepte/Grundlagen, die mir hier fehlen könnten.

Thanks :)

+0

http://pnnr.co/edit/7yz2DUttPjI5GVJkvr5h?open = app% 2Fapp.component.ts & p = info – Basit

-3

Dies sollte funktionieren, wenn Ihr ion-list Element eine feste Höhe hat.

<ion-list id="item-list"> 
    <ion-item> item 1 </ion-item> 
    <ion-item> item 2 </ion-item> 
    [...] 
    <ion-item> item 20 </ion-item> 
    <ion-item> item 21 </ion-item> 
</ion-list> 

[...] 

<script> 
    var itemList = document.getElementById("item-list"); 
    itemList.scrollTop = itemList.scrollHeight 
</script> 
+0

Entschuldigung aber nichts passiert:/ –

+0

Könnten Sie ein wenig mehr Code teilen? Wie ist das eine Vorlage oder wo erwartest du das Javascript runterscrollen? – rinukkusu

+0

hey, tut mir leid, es funktioniert auf coypen, das Problem hier ist, dass ich flexbox benutze, damit es nicht damit arbeitet. versuchen Sie es ein wenig mehr und geben Sie Feedback in Minuten auf. –

17

Hier ist, wie ich es tat:

chatPage.html

<ion-content #content padding class="chatPage"> 

    <ion-list no-lines> 
    <ion-item *ngFor="let msg of messages" > 
     <chat-bubble [message]="msg"></chat-bubble> 
    </ion-item> 
    </ion-list> 

</ion-content> 

Das wichtige Bit in chatPage.html ist #content auf <ion-content>. Ich verwende die #content Kennung, um einen Verweis auf <ion-content> in meinem chatPage.js mit der ViewChild zu erhalten.

nun für die eigentliche Bildlauf-Logik:

chatPage.js

import {Component, ViewChild} from '@angular/core'; 

@Component({ 
    templateUrl: 'build/pages/chatPage/chatPage.html', 
    queries: { 
    content: new ViewChild('content') 
    } 
}) 
export class ChatPage { 
    constructor() { 

    } 

    //scrolls to bottom whenever the page has loaded 
    ionViewDidEnter(){ 
    this.content.scrollToBottom(300);//300ms animation speed 
    } 
} 

Auch wenn mein chatPage eine andere Chat-Nachricht in der Liste anzuzeigen muss (entweder eine neue Nachricht empfangen wird, oder eine neue Nachricht gesendet wird), habe ich den Code unten bin mit blättern auf den neuen Boden:

setTimeout(() => { 
    this.content.scrollToBottom(300);//300ms animation speed 
}); 

Update für Typoskript

Als ich diese Antwort gab, arbeitete ich mit der JavaScript-Version des Ionic 2-Projekts. Im Laufe der Zeit wechselte ich Typoskript, aber ich habe vergessen, die Antwort zu aktualisieren, so, hier ist ein kleines Update für chatPage.js (ts):

chatPage.ts

import {Component, ViewChild} from '@angular/core'; 

@Component({ 
    templateUrl: 'chatPage.html' 
}) 
export class ChatPage { 
    @ViewChild('content') content:any; 

    constructor() { } 

    //scrolls to bottom whenever the page has loaded 
    ionViewDidEnter(){ 
    this.content.scrollToBottom(300);//300ms animation speed 
    } 
} 
+0

http://plnkr.co/edit/7yz2DUttPjI5GVJkvr5h?open=app%2Fapp.component.ts&p=info – Basit

+0

behebt das Timeout die Verzögerung des ngFür die Aktualisierung? Denn ohne Zeitüberschreitung scrollt es nach unten, fügt aber nach dem Scrollen die neue Zeile hinzu. – Ismail

+2

@Ismail Das stimmt. Deshalb wurde die Zeitüberschreitung hinzugefügt. – smukov

-3

Just do it:

public ionViewDidEnter(){ 
    this.content.scrollToBottom(300); 
} 
13

die ionische hat eine Option, dies zu tun und funktioniert recht gut: und das ist die am besten geeignete Art und Weise mit Winkel 2+ und Ionic.

+0

Eine ionische Lösung statt einer eckigen, verdient mehr upvotes – Ivaro18

+1

Wie würden Sie diese Methode aufrufen, wenn eine neue Nachricht oder Inhalt der aktuellen Seite hinzugefügt wird. Ich kann auf ionViewWillEnter nach unten scrollen, aber die App stoppt, wenn ich sie anrufe, wenn ein Inhalt hinzugefügt wird. – fanbondi

+0

@fanbondi Worüber sprichst du, ruf einfach den Bildlauf nach unten, wenn die Daten hinzugefügt werden –

0

Eine andere Lösung besteht darin, Änderungen in der Bildlaufansicht zu "beobachten" und automatisch zu scrollen. , d. H. Wenn neue HTML-Elemente vorhanden sind, in denen die Nachrichten angezeigt werden, scrollen Sie nach unten.

export class MessagesPage implements OnInit, OnDestroy { 
    autoScroller: MutationObserver; 

    ngOnInit() { 
    this.autoScroller = this.autoScroll(); 
    } 

    ngOnDestroy() { 
    this.autoScroller.disconnect(); 
    } 

    autoScroll(): MutationObserver { 
    const autoScroller = new MutationObserver(this.scrollDown.bind(this)); 

    autoScroller.observe(this.messagesList, { 
     childList: true, 
     subtree: true 
    }); 

    return autoScroller; 
    } 

    scrollDown(): void { 
    this.scroller.scrollTop = this.scroller.scrollHeight; 
    this.messageEditor.focus(); 
    } 

    private get messageEditor(): HTMLInputElement { 
    return <HTMLInputElement>document.querySelector('ion-input'); 
    } 

    private get messagesList(): Element { 
    return document.querySelector('.messages'); 
    } 

    private get scroller(): Element { 
    return this.messagesList.querySelector('.scroll-content'); 
    } 
} 

Vorlage:

<ion-content> 
    <ion-scroll scrollY="true" class="messages"> 
    <ion-list> 
     <div *ngFor="let message of messages"> 
     <p [innerHtml]="message.text"></p> 
     </div> 
    </ion-list> 
    </ion-scroll> 
</ion-content> 

<ion-footer> 
    <ion-toolbar> 
    <ion-input [(ngModel)]="message" type="text" placeholder="Write a message..." autocomplete="true" spellcheck="true" tappable></ion-input> 
    <ion-buttons end> 
     <button ion-button icon-only (click)="sendMessage()"> 
     <ion-icon name="paper-plane"></ion-icon> 
     </button> 
    </ion-buttons> 
    </ion-toolbar> 
</ion-footer> 

(nehmen von Ionic2CLI-Meteor-WhatsApp on Github)

1

Dieser jemand helfen könnte, habe ich in Ionic forum ähnliche Antwort gegeben. Dies ist in Ionic 3 implementiert.

Ich verwendete ngAfterViewChecked(), um diese Funktion zu erreichen. meine Codestruktur ist folgende -

home.html -

<ion-content padding> 
    <div #scrollMe id="messages-container" style="overflow: auto; height: 100%;"> 
     // All messages elemets. Scroll 
    </div> 
</ion-content> 

home.ts -

import { Component,ViewChild, AfterViewChecked, * * } from '@angular/core'; 
. 
. 
export class HomePage implements AfterViewChecked{ 
    // used for scrolling the pane 
    @ViewChild('scrollMe') private myScrollContainer: ElementRef; 

    ngAfterViewChecked() { 
     this.scrollToBottom(); 
    } 

    scrollToBottom(): void { 
     // method used to enable scrolling 
     this.myScrollContainer.nativeElement.scrollTop = this.myScrollContainer.nativeElement.scrollHeight; 
    } 
} 

.scrollTop und .scrollHeight sind Eigenschaften JavaScript, see here.

1

Ich habe eine Überprüfung hinzugefügt, um festzustellen, ob der Benutzer versucht hat, nach oben zu scrollen.

<div style="overflow: scroll; height: xyz;" #scrollMe [scrollTop]="scrollMe.scrollHeight"> 
    <div class="..." 
     *ngFor="..." 
     ...> 
    </div> 
</div>