[SOLVED] Autocomplete "Cannot read property 'create' of undefined"

Hi. I’m trying to use the Autocomplete component.
I’m declaring the autocomplete inside the page:init but I get the following error:

Uncaught TypeError: Cannot read property ‘create’ of undefined

Only when I declare the autocomplete inside a function works.
for example:

function myFunction() {
  var autocompleteDropdownSimple = app.autocomplete.create({
    inputEl: '#autocomplete-dropdown',
    openIn: 'dropdown',
    source: function (query, render) {
      if (localStorage.getItem('dniGuardados') != null) {
        var dniGuardadosArray = (localStorage.getItem('dniGuardados')).split("-");
        var results = [];
        // Find matched items
        for (var i = 0; i < dniGuardadosArray.length; i++) {
          if (dniGuardadosArray[i].toLowerCase().indexOf(query.toLowerCase()) >= 0) results.push(dniGuardadosArray[i]);
        }
        // Render items by passing array with result items
        render(results);
      }
    }
  });
}

And then if I call the function works.
I remember in past versions that I can declare a component just inside page:init.
What’s the right way to use this?

PS: I have different JScript files so I have declared the Framework7 like this window.app = new Framework7.

Edit: Calling the function with the autocomplete inside doesn’t work and I get the same error.

Make sure you have included bundle version of Framework7 JS framework7.bundle.js

I have this on my app.js file:
import Framework7 from 'framework7/framework7.esm.bundle.js';
On the login.js file that I want to use the autocomplete I have this import $$ from 'dom7';
If I try to include the bundle version on login.js I get the same error.

Still can’t make it work. Could be the problem that Autocomplete is trying to initialize before the login page load?

Can you show the full code of that page?

Yes, sure.
This is the login.f7.html page:

<template>
  <div class="page no-navbar no-toolbar no-swipeback" data-name="login">

    <!-- Scrollable page content-->
    <div class="page-content login-content bg-login-custom">
      <div class="block text-align-center margin-top">
        <img src="static/logo.png" width="200">
      </div>
      <div class="list inset bg-login-list-custom">
        <ul>
          <li class="item-content item-input theme-dark">
            <div class="item-inner">
              <div class="item-title item-floating-label">D.N.I.</div>
              <div class="item-input-wrap">
                <input id="autocomplete-dropdown" class="text-color-white" type="number" name="dni-paciente" placeholder="D.N.I." value="38323460">
                <span class="input-clear-button"></span>
              </div>
            </div>
          </li>
        </ul>
      </div>
      <div class="block">
        <p class="row">
          <a href="#" class="col button button-raised button-fill login-button md-only">Ingresar</a>
          <a href="#" class="col button button-fill login-button ios-only">Ingresar</a>
        </p>
        <p class="row">
          <a href="/registro/" class="col button register-button text-color-white">Registrarme como paciente</a>
        </p>
      </div>
    </div>
  </div>
</template>
<script>
import Framework7 from 'framework7/framework7.esm.bundle.js';
import utils from '../js/login.js';
export default {}
</script>

And this is the login.js file:

import $$ from 'dom7';


$$(document).on('page:init', '.page[data-name="login"]', function (e) {


  $$('.login-content .login-button').on('click', function () {
    console.log("click");
    var dniPaciente = $$('.login-content [name="dni-paciente"]').val().trim();

    if (dniPaciente == "") {
      app.dialog.alert("Debe ingresar un D.N.I.");
    }
    else {
      login(dniPaciente);
    }

  });


  $$('.login-content .guardar-dni-button').on('click', function () {
    var dniPaciente = $$('.login-content [name="dni-paciente"]').val().trim();

    if (dniPaciente == "") {
      app.dialog.alert("Debe ingresar un D.N.I.");
    }
    else {
      guardarDni(dniPaciente);
    }
  });

});




function login(dniPaciente) {

  var urlLogin = app_cliente + "pf=dame_tipo&p0="+dniPaciente;

  app.preloader.show();
  app.request.get(urlLogin, function(respuesta) {
    console.log("response:"+respuesta);
    if (respuesta.trim() == "P") {
      guardarDni(dniPaciente);
      comprobarTurnosPendientes(dniPaciente);
    }
    else if (respuesta.trim() == "E") {
      app.dialog.alert("¡Ups!<br> Parece que no se encuentra registrado.");
    }
  app.preloader.hide();
  },
  //Error
  function(xhr, status) {
    app.preloader.hide();
    alert(xhr);
    alert("status:"+status);
  });
}


function comprobarTurnosPendientes(dniPaciente) {
  var urlListaTurnosPendientes = app_cliente + "pf=dame_turp&p0=" + dniPaciente;

  app.preloader.show();
  app.request.json(urlListaTurnosPendientes, function(respuesta) {
    console.log(respuesta);
    if (respuesta.turnos == "") {
      app.views.main.router.navigate('/clinicas/' + dniPaciente);
    }
    else {
      app.views.main.router.navigate('/turnospendientes/' + dniPaciente);
    }

    app.preloader.hide();
  },
  //Error
  function(xhr, status) {
    app.preloader.hide();
    alert(xhr);
    alert("status:"+status);
  });
}





function guardarDni(dniPaciente) {

  var dniGuardados = localStorage.getItem('dniGuardados');

  if (dniGuardados === null) {
    console.log("entro if");
    localStorage.setItem('dniGuardados', dniPaciente.trim());
  }
  else if (!dniGuardados.includes(dniPaciente)) {
    console.log("entro else");
    var dniAux = dniGuardados + "-" + dniPaciente.trim();
    localStorage.setItem('dniGuardados', dniAux);
  }

}

function cargarAutocompletar() {
  var autocompleteDropdownSimple = app.autocomplete.create({
    inputEl: '#autocomplete-dropdown',
    openIn: 'dropdown',
    source: function (query, render) {
      if (localStorage.getItem('dniGuardados') != null) {
        var dniGuardadosArray = (localStorage.getItem('dniGuardados')).split("-");
        var results = [];
        // Find matched items
        for (var i = 0; i < dniGuardadosArray.length; i++) {
          if (dniGuardadosArray[i].toLowerCase().indexOf(query.toLowerCase()) >= 0) results.push(dniGuardadosArray[i]);
        }
        // Render items by passing array with result items
        render(results);
      }
    }
  });
}

I tried to load the Autocomplete through a function when login is ready (page:init), but won’t work. And I also tried to put the autocomplete var without function when login is ready (page:init), but won’t work either.

There is something extremely wrong happening.
You shouldn’t import Framework7 and utils here:

<script>
import Framework7 from 'framework7/framework7.esm.bundle.js';
import utils from '../js/login.js';
export default {}
</script>

Why if you don’t use it here?
You should import bundle only once, in the file where you call new Framework7().

Also, put all this page related logic to component methods and event handlers, e.g.:

<script>

export default {
  on: {
    pageInit() { ...  }
  }
}
</script>

Sorry, I forgot to delete that line. Used that import there just to test if it would work.
Actually I’m importing Framework7 and utils on app.js which is where I call new Framework7().
Ok, I will try to put all the logic on the <script>.

Ok, I came to this conclusion and autocomplete now works. Is it correct?

<script>
export default {
  methods: {
    login: function(dniPaciente) {
      var self = this;
      var urlLogin = app_cliente + "pf=dame_tipo&p0="+dniPaciente;

      app.preloader.show();
      app.request.get(urlLogin, function(respuesta) {
        console.log("response:"+respuesta);
        if (respuesta.trim() == "P") {
          self.guardarDni(dniPaciente);
          self.comprobarTurnosPendientes(dniPaciente);
        }
        else if (respuesta.trim() == "E") {
          app.dialog.alert("¡Ups!<br> Parece que no se encuentra registrado.");
        }
      app.preloader.hide();
      },
      //Error
      function(xhr, status) {
        app.preloader.hide();
        alert(xhr);
        alert("status:"+status);
      });
    },
    comprobarTurnosPendientes: function(dniPaciente) {
      var urlListaTurnosPendientes = app_cliente + "pf=dame_turp&p0=" + dniPaciente;

      app.preloader.show();
      app.request.json(urlListaTurnosPendientes, function(respuesta) {
        console.log(respuesta);
        if (respuesta.turnos == "") {
          app.views.main.router.navigate('/clinicas/' + dniPaciente);
        }
        else {
          app.views.main.router.navigate('/turnospendientes/' + dniPaciente);
        }

        app.preloader.hide();
      },
      //Error
      function(xhr, status) {
        app.preloader.hide();
        alert(xhr);
        alert("status:"+status);
      });
    },
    guardarDni: function(dniPaciente) {
      var dniGuardados = localStorage.getItem('dniGuardados');

      if (dniGuardados === null) {
        console.log("entro if");
        localStorage.setItem('dniGuardados', dniPaciente.trim());
      }
      else if (!dniGuardados.includes(dniPaciente)) {
        console.log("entro else");
        var dniAux = dniGuardados + "-" + dniPaciente.trim();
        localStorage.setItem('dniGuardados', dniAux);
      }
    }
  },
  on: {
    pageInit() {
      var self = this;
      var app = self.$app;
      var $ = self.$;

      self.autoCompleteDropdownSimple = app.autocomplete.create({
        inputEl: '#autocomplete-dropdown',
        openIn: 'dropdown',
        source: function (query, render) {
          if (localStorage.getItem('dniGuardados') != null) {
            var dniGuardadosArray = (localStorage.getItem('dniGuardados')).split("-");
            var results = [];
            // Find matched items
            for (var i = 0; i < dniGuardadosArray.length; i++) {
              if (dniGuardadosArray[i].toLowerCase().indexOf(query.toLowerCase()) >= 0) results.push(dniGuardadosArray[i]);
            }
            // Render items by passing array with result items
            render(results);
          }
        }
      });

      $('.login-content .login-button').on('click', function () {
        console.log("click");
        var dniPaciente = $('.login-content [name="dni-paciente"]').val().trim();

        if (dniPaciente == "") {
          app.dialog.alert("Debe ingresar un D.N.I.");
        }
        else {
          self.login(dniPaciente);
        }

      });
    }
  }
}
</script>

Yes, this is correct

1 Like

Thanks a lot! I understand a little more how it works now.