0

I am getting this error "Cannot read property 'scrollToBottom' of undefined" and haven't got a solution to this anywhere, hence this post:

Here is my use case: I have a custom accordion list, and on click of one of the list (since it will have some content) I want the user not to scroll to the bottom , hence using that property. I have only pasted the relevant code

This is my .ts

import { Component, ViewChild } from '@angular/core';
import { NavController,Platform, Navbar, Content} from 'ionic-angular';
import { ToastController } from 'ionic-angular';
import { NativeStorage } from '@ionic-native/native-storage';
@Component({
selector: 'page-profile',
templateUrl: 'profile.html'
})
export class ProfilePage {  
@ViewChild('content') content: any;  
constructor(public navCtrl: NavController, private nativeStorage : NativeStorage, private toastCtrl : ToastController, platform : Platform  ) { 
// other methods 
}
 ionViewDidLoad()
  {
    this.IonAccordion()
  }

IonAccordion(){
    this.accElement = document.getElementsByClassName('ion-accordion-header');
    var i;
     for (i = 0; i < this.accElement.length; i++) {
      console.log(i)
      this.accElement[i].addEventListener("click", function() 
      {
        this.classList.toggle("active");
        console.log("click");
        var panel = this.nextElementSibling;
        if (panel.style.maxHeight){
          console.log(panel.style.maxHeight);
          panel.style.maxHeight = null;
        } else { 
          panel.style.maxHeight = panel.scrollHeight + "px";
          this.content.scrollToBottom(300);
        } 
      });
    }
  }
}

This is my .html file,

<ion-content #content>
<ion-row>
    <ion-col>
    <div class="ion-accordion-header">Accordion 1 </div>
    <div class="panel">
       <p>Accordion content</p>
    </div>
    </ion-col>
    </ion-row>
<ion-row>
    <ion-col>
    <div class="ion-accordion-header">Accordion 2 </div>
    <div class="panel">
       <p>Accordion content</p>
    </div>
    </ion-col>
    </ion-row>
</ion-content>

Version info

cli packages: (F:\classette\node_modules)

@ionic/cli-plugin-cordova       : 1.6.2
@ionic/cli-plugin-ionic-angular : 1.4.1
@ionic/cli-utils                : 1.7.0
ionic (Ionic CLI)               : 3.7.0

global packages:

Cordova CLI : 7.0.1

local packages:

@ionic/app-scripts : 1.3.7
Cordova Platforms  : android 6.2.3
Ionic Framework    : ionic-angular 3.3.0

System:

Node : v6.10.2
OS   : Windows 10
npm  : 3.10.10
Melchia
  • 16,699
  • 16
  • 70
  • 93
Arun-
  • 660
  • 3
  • 16
  • 33
  • `this.accElement[i].addEventListener("click", function()` use arrow function here – Suraj Rao Feb 20 '18 at 13:30
  • Possible duplicate of [When should I use Arrow functions in ECMAScript 6?](https://stackoverflow.com/questions/22939130/when-should-i-use-arrow-functions-in-ecmascript-6) – Suraj Rao Feb 20 '18 at 13:30
  • @SurajRao, thank you, however, I don't get it how will that impact my scrollToBottom method? can you please elaborate? – Arun- Feb 20 '18 at 13:40
  • you are using `this`.. which will point to a different context when you use `function` callback and content will not exist. arrow functions dont set `this` its context depends on where it is defined. – Suraj Rao Feb 20 '18 at 13:41
  • if I use arrow function then I don't get access to nextElementSibling because it is using 'this' context. I guess I am wrong somewhere. If possible can you please edit the code and elaborate a bit more? – Arun- Feb 20 '18 at 13:53
  • maybe you havent set it correctly.. you would get access to the correct `this` in arrow – Suraj Rao Feb 20 '18 at 13:56

3 Answers3

2

Similar problem and my solution. Ionic 4 and Angular 8.

// header
import { ViewChild } from '@angular/core';
import { IonContent } from '@ionic/angular';

//elements
@ViewChild(IonContent, {static: true}) content: IonContent;

//functions
this.content.scrollToTop(500);
this.content.scrollToBottom(500);
  • Thanks. damn breaking changes. finally i found your post and solve my problem with latest ionic ;) – Budi Mar 13 '20 at 19:49
1

This in your function no longer points to your class but it now refers to the DOM object inside your method IonAccordion. Use this trick instead:

import { Content } from 'ionic-angular';

@ViewChild(Content) content: Content;

    IonAccordion(){
        const scope = this;
        this.accElement = document.getElementsByClassName('ion-accordion-header');
        var i;
         for (i = 0; i < this.accElement.length; i++) {
          console.log(i)
          this.accElement[i].addEventListener("click", function() 
          {
            this.classList.toggle("active");
            console.log("click");
            var panel = this.nextElementSibling;
            if (panel.style.maxHeight){
              console.log(panel.style.maxHeight);
              panel.style.maxHeight = null;
            } else { 
              panel.style.maxHeight = panel.scrollHeight + "px";
              scope.content.scrollToBottom(300);
            } 
          });
        }
      }
Melchia
  • 16,699
  • 16
  • 70
  • 93
0

Besides the fat arrow function problem you've not imported the content from ionic-angular, so you're not targeting your page content. Change your code to this:

import { Content } from 'ionic-angular';

@ViewChild(Content) content: Content;

After this your scrollToBottom method should work.

Gabriel Barreto
  • 6,103
  • 1
  • 22
  • 45
  • Oh I missed copying it here, It is indeed imported. My bad, to miss that line of code. – Arun- Feb 20 '18 at 13:56
  • I am getting decleration expected after i used this "@ViewChild(Content) content: Content;" – Arun- Feb 20 '18 at 14:06