0

I'm using Laravel with Alpinejs and webRTC to check if the user has the camera on or not. webRTC part works fine and it detects camera. But the x-text value which shows if the camera is on or off, doesn't get updated after the webRTC stream is obtained.

<div class="card">
    <div class="card-header font-bold">Preparation Page</div>
    <div class="card-body">
        {!! $exam->bo_exam_instruction !!}
        <div class="mt-2">
            Camera : <span x-text="isOpen ? 'On' : 'Off'" class="badge" :class="cameraClasses()"></span>
        </div>
        <div>
            <form action="{{ route('student.startOlympiad', $exam->id) }}" method="POST"
                x-ref="examForm">
                @csrf
                <button class="btn mt-2" :class="buttonClasses()"
                    x-on:click.prevent="confirmStartExam()">
                    Start Exam</button>
            </form>
        </div>
    </div>
</div>
@push('extra_js')
    <script>
        function componentData() {
            return {
                isOpen: false,
                cameraClasses() {
                    console.log("isOpen:", this.isOpen);
                    return {
                        // <span class="badge badge-danger">Danger</span>
                        'badge-danger': !this.isOpen,
                        'badge-success': this.isOpen
                    }
                },
                adapter: {
                    browserDetails: {
                        browser: navigator.userAgent,
                        version: navigator.appVersion
                    }
                },
                buttonClasses() {
                    return {
                        'btn-primary': !this.isOpen,
                        'btn-secondary': this.isOpen
                    };
                },
                confirmStartExam() {
                    if (this.isOpen) {
                        Swal.fire({
                            title: 'Are you sure?',
                            text: 'Once you start the exam, you cannot go back!',
                            icon: 'warning',
                            showCancelButton: true,
                            confirmButtonColor: '#3085d6',
                            cancelButtonColor: '#d33',
                            confirmButtonText: 'Yes, start the exam!'
                        }).then((result) => {
                            if (result.isConfirmed) {
                                this.startExam();
                            }
                        });
                    } else {
                        Swal.fire({
                            title: 'Camera Permission!',
                            text: 'Please allow camera permissions',
                            icon: 'info',
                        })
                    }
                },
                startExam() {
                    // Submit the form using Alpine.js
                    this.$refs.examForm.submit();
                },
            }
        }

        const data = componentData();
        async function openMediaDevices(constraints) {
            try {
                const stream = await navigator.mediaDevices.getUserMedia(constraints);
                // If stream is obtained, set isOpen to true
                if (stream) {
                    console.log(stream); //gets stream
                    data.isOpen = true;
                    console.log(data.isOpen); //comes true
                }
                return stream;
            } catch (error) {
                console.error('Error accessing media devices.', error);
                return null;
            }
        }

        window.onload = async function() {
            await openMediaDevices({
                video: true
            });
            console.log("Final isOpen:", data.isOpen);
        }
    </script>
@endpush

when the data.isOpen = true; x-text="isOpen ? 'On' : 'Off'" this should show "ON". it still shows "OFF"

1 Answer 1

0

The component data is encapsulated within that component, so you can't directly edit isOpen from outside of the component like you're trying to.

You could use an event to communicate with your component, but why not just move the openMediaDevices function onto the component itself? Then you can call it from the component's init() function and change the value of this.isOpen from there:

function componentData() {
  return {
    isOpen: false,
    // ... other properties and methods
    async openMediaDevices(constraints) {
      try {
        const stream = await navigator.mediaDevices.getUserMedia(constraints);
        if (stream) {
          this.isOpen = true;
        }
        return stream;
      } catch (error) {
        console.error('Error accessing media devices.', error);
        return null;
      }
    },
    async init() {
      await this.openMediaDevices({
        video: true,
      });
      console.log('Final isOpen:', this.isOpen);
    },
  };
}

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.