0
votes

In thread Which limitations v-model has in Vue 2.x?, I learned how to link parent and child components v-model. The suggested solution is:

--- ParentTemplate:
<Child v-model="formData"></Child>

-- ChildTemplate:
<input v-model="localValue">

-- ChildScript:
computed: {
    localValue: {
      get() {
        return this.value;
      },
      set(localValue) {
        this.$emit('input', localValue);
      },
    },
  },

Unfortunately, I could not re-write it to vue-class-component syntax. Below code neither works nor should work:

export default class TextEditor extends Vue {

  @Prop({ type: String, required: true }) private readonly value!: string;


  private get localValue(): string {
    return this.value;
  }

  private set localValue(newValue: string) {
    this.$emit("input", newValue);
  }
}

The answer to question how to write computed setters in class-based components in vuejs is not applicable to vue component properties because properties are readonly. So I can't write this.value = newValue.

Problem with straight value usage##

<EditorImplementation 
  :value="value" 
  @input="(value) => { onInput(value) }" 
/>
@Component({
  components {
    EditorImplementation: CK_Editor.component
  }
})
export default class TextEditor extends Vue {

  @Prop({ type: String, required: true }) private readonly value!: string;


  @Emit("input")
  private onInput(value: string): void {
    console.log("checkpoint");
    console.log(this.value);
  }
}

Assume that initially value is empty string.

  1. Input "f"
  2. Log will be "checkpoint" ""
  3. Input "a"
  4. Log will be "checkpoint" "f"
  5. Input "d"
  6. Log will be "checkpoint" "fa"

And so on.

1
I don't think this is the best way to go about it. You shouldn't mutate props directly. Why can't you just put the value props directly in your template. Something like <input :value="value">Tony
@Tony, thank you for the answer. With EditorImplementation(:value="value" @input="(value) => { onInput(value) }"), in @Emit("input") private onInput(value: string): void { console.log(this.value); } I always get output with previous value, not actual. E. g. on first input, value is still empty string. Is it normal?Takeshi Tokugawa YD
Hi, please edit the post and add this function for better readability.Tony
@Tony, Roger that, done.Takeshi Tokugawa YD

1 Answers

1
votes

At the moment, it seems like you get an input value from the parent, and then you change the value, and emit that value back to the parent. That seems like an anti-pattern.

Please try this

Your EditorImplementation component will be something like

 <input
  ....
  :value="value"
  @input="$emit('input', $event.target.value)"
 />
 
@Prop({default: ''}) readonly value!: string

And then

<EditorImplementation 
  v-model="localValue"
  @input="(value) => { onInput(value) }" 
/>

and you import it into the Text Editor file like you have done

@Component({
  components {
    EditorImplementation: CK_Editor.component
  }
})
export default class TextEditor extends Vue {
  private localValue = '';

  @Emit("input")
  private onInput(value: string): void {
 
  }
}