Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

vue.js - Uncaught TypeError: Cannot read property '$forContext' of null

Tags:

vue.js

I have encountered a very strange issue. everything seems to be working correctly, but on submission of inputs (I tried both the form submit event when i was using a <form/> element and the keyop.enter event I get the following error in my JS console and cannot figure it out.

the console error is as follows:

Uncaught TypeError: Cannot read property '$forContext' of null
Watcher.set @ bundle.js:12831
(anonymous function) @ bundle.js:17611
Directive._withLock @ bundle.js:17628
Directive.set @ bundle.js:17610
listener.rawListener @ bundle.js:13664
n.event.dispatch @ jquery.js:4435
r.handle @ jquery.js:4121
remove @ bundle.js:10835
(anonymous function) @ bundle.js:10687applyTransition @ bundle.js:10715
removeWithTransition @ bundle.js:10686
singleRemove @ bundle.js:14172
remove @ bundle.js:14374
update @ bundle.js:14359
_update @ bundle.js:17482
Watcher.run @ bundle.js:12933
runBatcherQueue @ bundle.js:12666
flushBatcherQueue @ bundle.js:12642
nextTickHandler @ bundle.js:10079

my component code:

module.exports = {
    data: function () {
        return {
            message: "",
            disabled: true,
            progress: 1,
            statusMessage: {},
            displayPhotoForm: false,
            displayVideoForm: false,
            videoUrl: ""
        }
    },
    computed: {
        messageLength: function() {
            if (this.message === "") {
                return 0;
            }
            return this.message.length;
        }
    },
    props: [
        'api-endpoint'
    ],
    methods: {
        advance: function() {
            if (this.progress == 1) {
                this.postStatus();
            }
            if (this.progress == 2 && this.videoUrl !== "") {
                this.putVideoUrl();
            }
            this.progress++;
        },
        postStatus: function () {
            this.$http.post(this.apiEndpoint, {message: this.message}, function (data, status, request) {
                this.message = '';
                this.statusMessage = data.data;
            }).error(function (data, status, request) {
                //
            });
        },
        putVideoUrl: function() {
            this.$http.put(this.apiEndpoint+'/'+this.statusMessage.id, {videoUrl: this.videoUrl}, function (data, status, request) {
                this.statusMessage = data.data;
            }).error(function (data, status, request) {
                //
            });
        }
    }
};

my component markup:

<status-message-form api-endpoint="{{ route('api.v1:statusMessages.store') }}" inline-template>
    <div class="row status-message-form p-y-2">
        <div class="container">
            <div class="row">
                <div class="col-sm-6 col-sm-offset-3 text-xs-center">
                    <h5>What's new with your business?</h5>
                    <div class="form">
                        <fieldset class="form-group" v-if="progress == 1">
                            <input @keydown.enter="advance" class="form-control" type="text" v-model="message" />
                        </fieldset>
                        <fieldset class="form-group" v-if="progress == 2">
                            <button @click="displayPhotoForm=true" class="btn btn-secondary">upload photo</button>
                            <button @click="displayVideoForm=true" class="btn btn-secondary">add video</button>
                        </fieldset>
                        <fieldset class="form-group" v-if="progress == 2 && displayVideoForm">
                            <input @keydown.enter="advance" class="form-control" type="text" v-model="videoUrl" placeholder="https://youtube.com/?v=xyz123"/>
                        </fieldset>
                        <fieldset class="form-group" v-if="progress == 2 && displayPhotoForm">
                            <h6>photo uploader?</h6>
                        </fieldset>
                        <fieldset class="form-group" v-if="progress == 3">
                            step 3
                        </fieldset>
                    </div>
                    <div class="character-count" v-if="progress == 1">
                        @{{ 150 - messageLength }} Characters Remaining
                    </div>
                    <progress class="progress" value="@{{ progress }}" max="3">
                        PROGRESS - @{{ progress }}
                    </progress>
                    <pre>@{{ statusMessage | json }}</pre>
                </div>
            </div>
        </div>
    </div>
</status-message-form>
like image 565
Erik Avatar asked Jan 07 '23 16:01

Erik


2 Answers

Finally I found the problem and solve it. It is nothing about jQuery or Vue. It is a code error. When somebody click the enter key, <input> will update its modal, all things happy. But a event typed 'input' is sent and reached in the next tick. At that time, <input> is already gone because of the v-if directive. So no scope is there and the error occurs.

To solve this problem, just use v-show instead of v-if for keeping the <input> tag existing.

like image 172
holmescn Avatar answered Jan 09 '23 06:01

holmescn


I ran into this today and @holmescn's answer makes perfect sense. You can also add the "lazy" attribute so the model isn't updated until a "change" event is fired from the input.

<input type="text" v-model="whatever" v-if="whateverAndEver" lazy />

like image 42
Benjamin Oman Avatar answered Jan 09 '23 06:01

Benjamin Oman