2

How would I correctly access the nested json for stage.name in the example below?

You can see in the template I am trying to access stage name.

vue.js

created() {
    url="http://{{ api_endpoint }}"
    fetch(url)
        .then(response => response.json())
        .then(body => {
            for(i=0; i<body.length; i++){
                this.job_execs.push({
                    'name': JSON.stringify(body[i].job.name),
                    'build_id': JSON.stringify(body[i].build_num),
                    'env': JSON.stringify(body[i].job.env),
                })
            }
    })



template: `
      <li v-for="item in this.job_execs">
        [[ item.build_num ]]
        <li v-if="stage in item.job">
          [[ stage.name ]]
        </li>
      </li>
    </ul>

example api

[
    {
        "build_num": 12,
        "job": {
            "name": "test-job",
            "env": "DEV",
            "tool": {
                "env": "DEV",
            },
            "product": {
                "name": "vuejs"
            },
            "platform": {
                "name": "none"
            },
            "stage": [
                {
                    "name": "stage1"
                },
                {
                    "name": "stage2"
                },
                {
                    "name": "stage3"
                },
            ]
        },
]

I am guessing I need to create a new list in the created hook and start pushing the stage names? But then I will have two lists? Not sure what is the best way to do this.

1 Answer 1

1

If you want to create an <li> for each stage it would be:

<li v-for="stage in item.job.stage">
  [[ stage.name ]]
</li>

Note v-for, not v-if.

You can think of v-for as being the template equivalent of this:

item.job.stage.forEach(stage => {
    // ...
})

If you just want the first one then it's:

<li>
  [[ item.job.stage[0].name ]]
</li>

If you did want to pursue the idea of creating a second list then you should do it using a computed property, no need to do anything in a created hook. In that computed property you could reduce down your data into a format that is easier to work with in your template. I'm not sure that's warranted in this case but if your needs are more complex than the example code you've posted then that might be a good way to go rather than writing a convoluted template.

Update:

So in full this would be:

<ul>
  <li v-for="item in job_execs">
    [[ item.build_num ]]
    <ul>
      <li v-for="stage in item.job.stage">
        [[ stage.name ]]
      </li>
    </ul>
  </li>
</ul>

In your JavaScript code there's no need for all that JSON.stringify stuff.

fetch(url)
    .then(response => response.json())
    .then(body => {
        this.job_execs = body
    })

If you want something a bit closer to your original code with build_num renamed to build_id then there are several options, such as:

fetch(url)
    .then(response => response.json())
    .then(body => {
        for (let i = 0; i < body.length; i++) {
            this.job_execs.push({
                build_id: body[i].build_num,
                job: body[i].job
            })
        }
    })

You'd then need to refer to build_num as build_id in your template.

Personally I'd be more inclined to use forEach, for/of or map instead of a straight for loop. e.g.:

fetch(url)
    .then(response => response.json())
    .then(body => {
        this.job_execs = body.map(item => {
            return {
                build_id: item.build_num,
                job: item.job
            }
        })
    })

All of this is only necessary if you really need to transform the format of the data though. Otherwise just stick to this.job_execs = body.

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

10 Comments

In this example - what if the number of stages for a given job is unknown? I want to list all the job stages but the number of job stages will be different based on the job
@david I believe that's what my first example does. It uses v-for to iterate over the array item.job.stage.
oh - did not even notice that. Thanks!
Two things: I think you mean {{ stage.name }} and not [[ stage.name ]], and you'll need to nest the second layer of lis inside of a ul or ol.
@DavidWeldon The question used [[ stage.name ]] so I followed suit. I assume he is either using an alternative templating engine or has set the delimiters option in Vue. vuejs.org/v2/api/#delimiters
|

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.