skip to Main Content

Using Alpine.js for the first time.

I have a video tag to show the camera feed, in a modal, which is initialized when the video tag is initialized using

<div x-data="initTestData()" @data-transfer.window="check=$event.detail.check; runningTest=true;" class="modal fade">

<video
    class="w-100 rounded"
    id="test-video"
    x-init="initTest(check)">
</video>

</div>

which is triggered by

<i @click="$dispatch('data-transfer', {check: check})" data-bs-toggle="modal" role="button"></i>

and the js is defined as

function initTestData() {
        console.log('init test data');
        return {
            check: null,
            resource: null,
            runningTest: false,
            initTest(check) {
                console.log('Check initialized: ', check);

                    const video = document.getElementById('test-video');
                    navigator.mediaDevices.getUserMedia({
                      video: {
                        facingMode: 'user'
                      }
                    }).then(stream => {
                      this.resource = stream;
                      // Older browsers may not have srcObject
                      if ("srcObject" in video) {
                        video.srcObject = stream;
                      } else {
                        // Avoid using this in new browsers, as it is going away.
                        // @ts-ignore
                        video.src = window.URL.createObjectURL(stream);
                      }
                      video.onloadedmetadata = function () {
                        video.play();
                      };
                    });
                
            },
            closeTest(check) {
                this.runningTest = false;
                if (this.resource) {
                    let tracks = this.resource.getTracks(); // get all tracks from the media stream
                    tracks.forEach(track => track.stop()); // stop each track
                }
            }
        }
    }

But the initTest() method is called only once. After the modal is closed and opened again, the initTest() method is not called to reinitialise the camera.

2

Answers


  1. Chosen as BEST ANSWER

    Got it solved by adding blank x-data on the video tag.

    <video
      x-data
      class="w-100 rounded"
      x-init="initTest(check);$watch('runningTest', (value) => value ? initTest(check) : '')"
      id="test-video">
    </video>
    

    It looks like $watch can only be used with x-data on the same element.


  2. x-init is called only once when the Alpine object is intialized.
    When you close the modal the object is still there and x-init is no more invoked.

    To resolve you can invoke initTest() in the event handler:

    @data-transfer.window="check=$event.detail.check; runningTest=true; initTest(check)"
    

    and remove x-init="initTest(check)"


    Another option can be adding a $watch over a variable:

    function initTestData() {
    
        return {
         
           //.....
    
           init() {
    
               // this is a possible solution if 'check' is boolean, adapt it to your needings
        
               this.$watch('check', value => {
                    value ? this.initTest() : this.closeTest();
           },
        
           //....
       }
    }
    

    And varying the value of the variable when dispatching the event.
    For example:

    <i @click="$dispatch('data-transfer', {check: !check})">
    

    But the event must be dispatched also in the modal "dismiss" to let closeTest() be called

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search