Inyourface
Inyourface

Reputation: 532

Value is not changing in real time -- VueJS

I am using a JS class, I have following code:

class Field {
    public Value = null;
    public Items = [];
    public UniqueKey = null;

    public getItems() {
        let items = [...this.Items];
        items = items.filter((item) => {
            if (item.VisibleIf) {
                const matched = item.VisibleIf.match(/\$\[input:(.*?)\]/g);
                if (matched?.length) {
                    const srv = Service.getInstance();
                    for (let match of matched) {
                        match = match.slice(8, -1);
                        if (srv.Fields?.length) {
                            let found = srv.Fields.find((x) => x.UniqueKey === match);
                            if (found) {
                                item.VisibleIf = item.VisibleIf.replace(
                                    `$[input:${match}]`,
                                    found.Value ?? ''
                                );
                                return JSON.parse('' + eval(item.VisibleIf));
                            }
                        }
                    }
                }
            }
            return true;
        });
        return items;
    }

    public getInputTitle() {
        let title = this.Title;
        const matched = title.match(/\$\[input:(.*?)\]/g);
        if (matched?.length && title) {
            const srv = Service.getInstance();
            for (let match of matched) {
                match = match.slice(8, -1);
                if (srv.Fields?.length) {
                    let found = srv.Fields.find((x) => x.UniqueKey === match);
                    if (found) {
                        title = title.replace(`$[input:${match}]`, found.Value ?? '');
                    }
                }
            }
        }
        return title;
    }
}

Now I have a Vue component:

<div v-for="Field in Fields" :key="Field.UniqueKey">
    <v-select
        v-if="Field.Type == 'Select'"
        :label="Field.getInputTitle()"
        v-model="Field.Value"
        :items="Field.getItems()"
        item-text="Value"
        item-value="Id"
    />
    <v-input
        v-else-if="Field.Type == 'Input'"
        v-model="Field.Value"
        :label="Field.getInputTitle()"
    />
</div>

// JS
const srv = Service.getInstance();
Fields = srv.getFields(); // <- API call will be there.

So basically, data comes from an API, having Title as Input $[input:uniqueKey], in a component I am looping over the data and generating the fields. See getInputTitle function in Field class, it works very well. All the fields which are dependent on the $[input:uniqueKey] are changing when I start typing into that field on which other fields are dependent.

Now I have pretty much same concept in the getItems function, so basically, what I want to do is whenever I type into a field and that field exists in the VisibleIf on the Items, the VisibleIf will be like '$[input:uniqueKey] < 1', or any other valid JavaScript expression which can be solved by eval function. But the getItems function is called only 1st time when page gets loaded, on the other hand the getInputTitle function which is pretty much same, gets called every time when I type into the field.

I tried to explain at my best, I will provide any necessary information if needed.

Any solution will be appreciated. Thanks.

Upvotes: 1

Views: 233

Answers (1)

U-Dev
U-Dev

Reputation: 1387

You are updating the Object itself in here:

item.VisibleIf = item.VisibleIf.replace( `$[input:${match}]`, found.Value ?? '' );

Even though you tried to copy the array, but you have done shallow copy of the object in here: let items = [...this.Config.Items];

I suggest the following solution:

const visibleIf = item.VisibleIf.replace(
    `$[input:${match}]`,
    found.Value ?? ''
);
const val = '' + helpers.evalExp('' + visibleIf);
if (helpers.isJSON(val)) {
    return JSON.parse(val);
}

Means instead of changing the VisibleIf object, just store it into the variable and just use that.

I hope that it will fix your issue. Let me know if it works.

Upvotes: 1

Related Questions