0

I have an object like this:

[

{"id":1,"parentId":null,"name":"Parent1"},

{"id":2,"parentId":null,"name":"Parent2"},

{"id":3,"parentId":null,"name":"Parent3"},

{"id":4,"parentId":1,"name":"Child1Parent1"},

{"id":5,"parentId":1,"name":"Child2Parent1"},

{"id":6,"parentId":2,"name":"Child1Parent2"},

{"id":7,"parentId":null,"name":"Parent4"}

... ]

I have to return grouped Array by Id and ParentId in table with expanded childs if exist like:

[

{

"id":1,"parentId":null,"name":"Parent1",

{"id":4,"parentId":1,"name":"Child1Parent1"},

{"id":5,"parentId":1,"name":"Child2Parent1"}

},

{

"id":2,"parentId":null,"name":"Parent2",

{"id":6,"parentId":2,"name":"Child1Parent2"}

},

{"id":3,"parentId":null,"name":"Parent3"},

... ]

2
  • You can only ask one question at a time. You can't use a question as an online tutorial getting you through building a website. That is to say we're only answering as long as you make your questions generic (useful for future visitors with a similar issue). If you keep changing one question based on where you are in your quest to build a website, that's only going to be useful to you, therefore off-topic on Stack Overflow. Commented May 11, 2020 at 17:01
  • Sure, i will make a new topic Commented May 11, 2020 at 17:16

2 Answers 2

1

I took the liberty to take @procoib's answer a bit further and I added a few more details to to it, allowing the markup to be more expressive:

Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({
  el: '#app',
  data: () => ({
    items: [
      { "id": 1, "parentId": null, "name": "Parent1" },
      { "id": 2, "parentId": null, "name": "Parent2" },
      { "id": 3, "parentId": null, "name": "Parent3" },
      { "id": 4, "parentId": 1, "name": "Child1Parent1" },
      { "id": 5, "parentId": 1, "name": "Child2Parent1" },
      { "id": 6, "parentId": 2, "name": "Child1Parent2" },
      { "id": 7, "parentId": null, "name": "Parent4" }
    ].map(i => ({ ...i,
      expanded: true
    }))
  }),
  computed: {
    parents() {
      return this.items.filter(g => !g.parentId)
    },
    children() {
      return this.items.filter(g => g.parentId)
    }
  },
  methods: {
    childrenOf(id) {
      return this.items.filter(g => g.parentId === id)
    }
  }
})
.cursor-pointer {
  cursor: pointer;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>

<div id="app">
  <table class="table table-sm">
    <thead>
      <tr>
        <th>ID</th>
        <th>parentId</th>
        <th>name</th>
      </tr>
    </thead>
    <tbody>
      <template v-for="parent in parents">
          <tr>
            <th colspan="3"
                class="bg-light">
                {{parent.name}}
                <code v-if="childrenOf(parent.id).length"
                      class="font-weight-light cursor-pointer"
                      @click="parent.expanded = !parent.expanded">[{{
                        parent.expanded ? 'hide' : 'show'
                      }}]</code>
            </th>
          </tr>
          <tr v-for="child in childrenOf(parent.id)" v-show="parent.expanded">
            <td v-text="child.id" />
            <td v-text="child.parentId"/>
            <td v-text="child.name"/>
          </tr>
        </template>
    </tbody>
  </table>
</div>

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

1 Comment

Please explain how that is part of current question. You must have skipped reading How to Ask.
1

From what i can understand from your list of objects, you want to link your child keys to parents. And display those to the template via a loop?

I would say the easiest thing to do with that data:

  • Create a template within the table tags to loop through every array using v-for, label this as parent.
  • Use a v-if against parentId to check and determine which object is a parent
  • Inside of this loop, create another row and loop through the children
  • Check against parentId to confirm its a child, then compare the child.parentId to parent.id

new Vue({
  el: "#app",
  data: {
   taskArray: [
    {"id":1,"parentId":null,"name":"Parent1"},
    {"id":2,"parentId":null,"name":"Parent2"},
    {"id":3,"parentId":null,"name":"Parent3"},
    {"id":4,"parentId":1,"name":"Child1Parent1"},
    {"id":5,"parentId":1,"name":"Child2Parent1"},
    {"id":6,"parentId":2,"name":"Child1Parent2"},
    {"id":7,"parentId":null,"name":"Parent4"}
 ]
  }
})
#customers {
  font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
  border-collapse: collapse;
  width: 100%;
}

#customers td, #customers th {
  border: 1px solid #ddd;
  padding: 8px;
}

#customers tr:hover {background-color: #ddd;}

#customers th {
  padding-top: 12px;
  padding-bottom: 12px;
  text-align: left;
  background-color: #4CAF50;
  color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <h2>Grouped array</h2>

  <table id="customers">
    <template v-for="parent in taskArray">
      <tr v-if="!parent.parentId">
        <td><b>{{ parent.name }}</b></td>
      </tr>
      <tr v-for="child in taskArray">
        <td v-if="child.parentId === parent.id" style="border:0px;background-color:#f2f2f2"> {{ child.name }}</td>
      </tr>
    </template>
  </table>
</div>

Jsfiddle for reference: https://jsfiddle.net/procoib/vcopwtk8/

2 Comments

Very good use of <template> tags and, indeed, I stand corrected, there's no actual need for grouping.
@kierusek Did any of these answers solve your original question?

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.