0

I've a problem, I cannot install on Angular Instascan library so I'm using it without installing, only import the script. To make it work I've to use JQuery into my ts file in the component, is there any way to call inside JQuery function a Typescript function to send the QR's content to my web service? I've been trying use Ajax to send the data directly to web service but isn't work.

QR's function is escanearQR and the function that I want to call is registrarAsistencia inside the scanner.addListener.

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { DatosService } from '../datos.service';
import Swal from 'sweetalert2';

declare var $: any;
declare var Instascan: any;
@Component({
  selector: 'app-toma-asistencia',
  templateUrl: './toma-asistencia.component.html',
  styleUrls: ['./toma-asistencia.component.css']
})
export class TomaAsistenciaComponent implements OnInit {

  constructor(private router: Router, public datos: DatosService) { }
  id_actividad_activa: string;
  id_evento_activo: string;
  actividad: any;
  participantes: any;
  qr:string;
  datosEscaner:string;

  obtenerParticipantes() {
    this.datos.getParticipantes(this.id_evento_activo, this.id_actividad_activa).subscribe(res => {
      this.participantes = res;
    }, error => {
      Swal.fire({
        icon: 'error',
        title: '¡Ups!',
        text: 'No hay participantes aún',
        timer: 2000
      });
    });
  }

  escanearQR(){
    $('#btnqr').empty();
    let scanner = new Instascan.Scanner({ video: document.getElementById('preview'), scanPeriod: 5, mirror: false });
                    scanner.addListener('scan', function(content){
            console.log(content);
            $('#codigoQR').val(content);
            //CALL HERE registrarAsistencia WITH content VALUE
                    });
                    Instascan.Camera.getCameras().then(function (cameras){
                        if(cameras.length>0){
                            scanner.start(cameras[0]);
                            $('[name="options"]').on('change',function(){
                                if($(this).val()==1){
                                    if(cameras[0]!=""){
                                        scanner.start(cameras[0]);
                                    }else{
                                        alert('No se ha encontrado camara frontal');
                                    }
                                }else if($(this).val()==2){
                                    if(cameras[1]!=""){
                                        scanner.start(cameras[1]);
                                    }else{
                                        alert('No se ha encontrado camara trasera');
                                    }
                                }
                            });
                        }else{
                            console.error('No se han encontrado camaras.');
                            alert('No se han encontrado camaras.');
                        }
                    }).catch(function(e){
                        console.error(e);
                        alert(e);
                    });
          
  }

  registrarAsistencia(){

  }

  cerrarEscaner(){
    window.location.reload();
  }

  ngOnInit(): void {
    this.id_actividad_activa = this.datos.getActividadActiva().id_ac;
    this.id_evento_activo = this.datos.getEventoActivo().id_evento;
    this.actividad = this.datos.getActividadActiva().nombre;
    this.obtenerParticipantes();
  }
}
Jesus Mg
  • 5
  • 2

1 Answers1

0

the issue you are facing is not related to Angular, but to the "this" scope in JavaScript functions instead.

Let's start from the beginning: functions declared with the "old" function keyword are a little bit forgetful. It means that they don't remember the value of this in the context they are declared, they use the value of this for the context they are executed.

Arrow Functions (*lambda functions if you are familiar with Java) are more powerful: they are able to remind the value of this intended as the scope of their declaration. In some way, the following examples do the same thing:

const bindedFn = (function() {}).bind(this);
const arrowFn = () => {};

As far as I can see in you code snippet, you do something like

$(this).val();

So I assume that this should be used as the context of execution by jQuery. How to solve this? Well, it's kinda easy if you know what a closure is and that every function in JavaScript is a closure. Declare a const before the scanner variable: will be used to hold the value of this as the instance of the component you are into or, even easier, the function in your component:

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { DatosService } from '../datos.service';
import Swal from 'sweetalert2';

declare var $: any;
declare var Instascan: any;
@Component({
  selector: 'app-toma-asistencia',
  templateUrl: './toma-asistencia.component.html',
  styleUrls: ['./toma-asistencia.component.css']
})
export class TomaAsistenciaComponent implements OnInit {

  constructor(private router: Router, public datos: DatosService) { }
  id_actividad_activa: string;
  id_evento_activo: string;
  actividad: any;
  participantes: any;
  qr:string;
  datosEscaner:string;

  obtenerParticipantes() {
    this.datos.getParticipantes(this.id_evento_activo, this.id_actividad_activa).subscribe(res => {
      this.participantes = res;
    }, error => {
      Swal.fire({
        icon: 'error',
        title: '¡Ups!',
        text: 'No hay participantes aún',
        timer: 2000
      });
    });
  }

  escanearQR(){
    $('#btnqr').empty();
    
    const registrarAsistencia = this.registrarAsistencia;
    
    let scanner = new Instascan.Scanner({ video: document.getElementById('preview'), scanPeriod: 5, mirror: false });
                    scanner.addListener('scan', function(content){
            console.log(content);
            $('#codigoQR').val(content);
            // CALL HERE registrarAsistencia WITH content VALUE
            registrarAsistencia(content);
                    });
                    Instascan.Camera.getCameras().then(function (cameras){
                        if(cameras.length>0){
                            scanner.start(cameras[0]);
                            $('[name="options"]').on('change',function(){
                                if($(this).val()==1){
                                    if(cameras[0]!=""){
                                        scanner.start(cameras[0]);
                                    }else{
                                        alert('No se ha encontrado camara frontal');
                                    }
                                }else if($(this).val()==2){
                                    if(cameras[1]!=""){
                                        scanner.start(cameras[1]);
                                    }else{
                                        alert('No se ha encontrado camara trasera');
                                    }
                                }
                            });
                        }else{
                            console.error('No se han encontrado camaras.');
                            alert('No se han encontrado camaras.');
                        }
                    }).catch(function(e){
                        console.error(e);
                        alert(e);
                    });
          
  }

  registrarAsistencia(){

  }

  cerrarEscaner(){
    window.location.reload();
  }

  ngOnInit(): void {
    this.id_actividad_activa = this.datos.getActividadActiva().id_ac;
    this.id_evento_activo = this.datos.getEventoActivo().id_evento;
    this.actividad = this.datos.getActividadActiva().nombre;
    this.obtenerParticipantes();
  }
}

For understanding the solution, please read carefully this link - javascript.info / closures. JavaScript.info is a bible for developers who want to understand how JavaScript works. Remember: TypeScript is just a superset of JavaScript, so you have to deeply understand the latter to properly code with the first.

Andrea Alhena
  • 986
  • 6
  • 9