4

I'm facing some problems with two-way data binding on deep nested object properties using vue v 3.0.5. My api returns a json which I then save in this exact way into my vue instance's data:

{
...
  "ratings": [
    {
      "id": 3,
      "text": "This is some text",
      "rating": {
        "plot": 3,
        "character development": 7,
        "cinematography": 5
      },
      "createdAt": "2022-02-01T17:23:48.032Z",
      "updatedAt": "2022-02-19T09:51:18.254Z",
      "publishedAt": "2022-02-01T17:24:12.878Z"
    },...
  ]
}

Now I've got a section in my template which renders the rating, passes the values to a component, which then displays the value on a scale from 1-10. Now I'm looking for a way to bind these individual values in rating for, let's say plot to a range input in my template, which looks something like this:

<template v-for="(value, component) in movie.ratings[0].rating">
              <div class="rating__label">{{ component }} {{value}}</div>
              <input type="range" min="0" max="10" v-bind="value">             
            </template>

in hoping that it should in theory bind the values for engine and gearbox inside rating to the slider, so when I update move the slider, the value inside ratings.rating gets updated. I have however not found any solution to this.

Can someone point me in the right direction here? Maybe more specifically, how to use v-bind here properly, for the binding to work? Is binding to deeply nested properties even possible?

Best regards derelektrischemoench

1 Answer 1

2

If I understood you correctly, maybe something like following snippet: (you can make method for input range changes and pass value, ratings index and property name, so you can use it this way for any ratings)

const app = Vue.createApp({
  data() {
    return {
      movie: {
        title: 'Some Movie',
        ratings: [{"id": 3, "text": "This is some text", "rating": {"plot": 3, "character development": 7, "cinematography": 5}, "createdAt": "2022-02-01T17:23:48.032Z", "updatedAt": "2022-02-19T09:51:18.254Z", "publishedAt": "2022-02-01T17:24:12.878Z"},{"id": 4, "text": "This is some text", "rating": {"plot": 4, "character development": 8, "cinematography": 6}, "createdAt": "2022-02-01T17:23:48.032Z", "updatedAt": "2022-02-19T09:51:18.254Z", "publishedAt": "2022-02-01T17:24:12.878Z"}]
      }
    };
  },
  methods: {
    changeVal(val, idx, field) {
      this.movie.ratings[idx].rating[field] = val
    }
  },
})
app.mount('#demo')
<script src="https://unpkg.com/[email protected]/dist/vue.global.prod.js"></script>
<div id="demo">
  <h5>{{ movie.title }} - ratings</h5>
  <div v-for="(i, idx) in movie.ratings.length" :key="idx">
    <div v-for="(value, component) in movie.ratings[idx].rating" :key="component">
      <div class="rating__label">{{ component }} {{ value }}</div>
      <input type="range" min="0" max="10" :value="value" @input="changeVal($event.target.value, idx, component)"> 
    </div>
    <hr>
  </div>
</div>

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

3 Comments

That did the trick. Thanks a lot!
and so when you change the sliders here, are those values written back to the data model?
@mike01010 hey mate, yes they are, v-model is shortcut for :value and @input

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.