Skip to content

Instantly share code, notes, and snippets.

@bayareawebpro
Last active April 29, 2020 04:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bayareawebpro/a21d5ec32c25238924dbc7a199da2688 to your computer and use it in GitHub Desktop.
Save bayareawebpro/a21d5ec32c25238924dbc7a199da2688 to your computer and use it in GitHub Desktop.
VueJS Binding External DOM Modifications

Vue Directive | Listen to External Dom Value Changes

Vue doesn't recognize the input change because the script is directly setting the input value at random intervals using the DOM. So, here's my solution in the form of a directive that will hook into the Element Descriptor and emit an input event so Vue will bind the new value to the form's v-model.

It can use a custom event or other element type as well.

Example (3rd Party Script):

element.value = x //Does not trigger the v-model update

Example Solution:

//Update VModel
<input
    type="text"
    id="x_token"
    name="x_token"
    v-model="form.x_token"
    v-external="{descriptor: 'value'}"
/>
//Emit Event
<input
    id="x_token"
    type="hidden"
    v-external="{descriptor: 'value', emit: 'updated'}" 
    @updated="..." 
/>
//HTML Tag (Haven't tried this yet, but in theory...)
<div
    id="data"
    data-attr=""
    v-external="{descriptor: 'dataset', emit: 'updated'}" 
    @updated="..." 
/>

Solution Directive Source:

 Vue.directive('external', {
        bind(el, {value}) {
            const {prototype} = (
                el instanceof HTMLInputElement
                ? HTMLInputElement
                : HTMLElement
            )
            const descriptor = Object.getOwnPropertyDescriptor(
                prototype,
                value.descriptor
            )
            Object.defineProperty(el, value.descriptor,
                Object.assign({}, descriptor, {
                    set(val) {
                        const result = descriptor.set.apply(this,arguments);
                        el.dispatchEvent(
                            value.hasOwnProperty('emit')
                            ? new CustomEvent(value.emit)
                            : new Event('input')
                        )
                        return result;
                    }
                })
            );
        },
        unbind(el, {value}) {
            const {prototype} = (
                el instanceof HTMLInputElement
                ? HTMLInputElement
                : HTMLElement
            )
            Object.defineProperty(el, value.descriptor,
                Object.getOwnPropertyDescriptor(
                    prototype,
                    value.descriptor
                )
            );
        }
    })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment