Recursively display dropdown in vue js
i have a table name called articles
id parent_id title
1 0 Profile
2 1 About Us
3 1 Why Us?
4 0 Kbow Us
now I want to create dropdown menu on vue laravel such that it recursively displays child category under parent category with proper indentation or - mark as per depth.E.g.:
<select>
<option value="1">Profile</option>
<option value="2">-About Us</option>
<option value="3">--Why Us</option>
<option value="4">Kbow Us</option>
</select>
I want to generate dropdown structure dynamically as like above recursively for any depth of child category in vue js.
vue.js
add a comment |
i have a table name called articles
id parent_id title
1 0 Profile
2 1 About Us
3 1 Why Us?
4 0 Kbow Us
now I want to create dropdown menu on vue laravel such that it recursively displays child category under parent category with proper indentation or - mark as per depth.E.g.:
<select>
<option value="1">Profile</option>
<option value="2">-About Us</option>
<option value="3">--Why Us</option>
<option value="4">Kbow Us</option>
</select>
I want to generate dropdown structure dynamically as like above recursively for any depth of child category in vue js.
vue.js
add a comment |
i have a table name called articles
id parent_id title
1 0 Profile
2 1 About Us
3 1 Why Us?
4 0 Kbow Us
now I want to create dropdown menu on vue laravel such that it recursively displays child category under parent category with proper indentation or - mark as per depth.E.g.:
<select>
<option value="1">Profile</option>
<option value="2">-About Us</option>
<option value="3">--Why Us</option>
<option value="4">Kbow Us</option>
</select>
I want to generate dropdown structure dynamically as like above recursively for any depth of child category in vue js.
vue.js
i have a table name called articles
id parent_id title
1 0 Profile
2 1 About Us
3 1 Why Us?
4 0 Kbow Us
now I want to create dropdown menu on vue laravel such that it recursively displays child category under parent category with proper indentation or - mark as per depth.E.g.:
<select>
<option value="1">Profile</option>
<option value="2">-About Us</option>
<option value="3">--Why Us</option>
<option value="4">Kbow Us</option>
</select>
I want to generate dropdown structure dynamically as like above recursively for any depth of child category in vue js.
vue.js
vue.js
edited Dec 30 '18 at 6:20
Dipesh Magar
asked Dec 30 '18 at 4:13
Dipesh MagarDipesh Magar
113
113
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
I would use a filter and a recursive function to walk each option back until no parent is found, keeping tracking of the depth and using that to append the indentation marks.
Since you're likely passing the articles to a view file (in a PHP array or collection), you can pass the data to a vue component like:
<my-nested-select :articles='{!! json_encode($articles) !!}'></my-nested-select>
Here's an example using generated data, the filter being the important part:
new Vue({
el: '#app',
data: () => ({
items: ,
selected: null
}),
created () {
// 1. Create some dummy data where each option has an increasing chance of being nested.
const tmp =
for (let i = 1; i <= 50; i++) {
let isChild = !!tmp.length ? Math.random() < ((i / 50) * tmp.length || 1) : null
let parent_id = isChild ? Math.ceil(Math.random() * tmp.length - 1) : null
tmp.push({
id: i,
parent_id,
text: `Option ${i}`
})
}
// 2. Sort the generated data so child options are in order following their parent option.
this.items = tmp.reduce((items, item) => {
if (!items.length || !item.parent_id) {
items.unshift(item)
} else {
const index = items.findIndex(({ id }) => id === item.parent_id)
if (index) {
items.splice(index, 0, item)
}
}
return items
}, ).reverse()
},
filters: {
depth (option, items) {
let depth = 0
// 3. The magic happens here with a recursive function to find the depth to which each option is nested.
const pad = ({ parent_id }) => {
if (!!parent_id) {
depth += 1
let parent = items.find(({ id }) => id === parent_id)
if (!parent) {
return depth
}
return pad(parent)
}
return depth
}
// 4. Call the recursive function above, create an array of hyphens and concat them together with the option's text.
return Array(pad(option)).fill('-').concat([' ', option.text]).join('')
}
}
})<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<select v-model="selected">
<option v-for="option in items" :value="option.id" :key="option.id">{{ option | depth(items) }}</option>
</select>
<h4>Data</h4>
<ul>
<li v-for="item in items" :key="item.id"><pre><code>{{ item }}</code></pre></li>
</ul>
</div>add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53975228%2frecursively-display-dropdown-in-vue-js%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I would use a filter and a recursive function to walk each option back until no parent is found, keeping tracking of the depth and using that to append the indentation marks.
Since you're likely passing the articles to a view file (in a PHP array or collection), you can pass the data to a vue component like:
<my-nested-select :articles='{!! json_encode($articles) !!}'></my-nested-select>
Here's an example using generated data, the filter being the important part:
new Vue({
el: '#app',
data: () => ({
items: ,
selected: null
}),
created () {
// 1. Create some dummy data where each option has an increasing chance of being nested.
const tmp =
for (let i = 1; i <= 50; i++) {
let isChild = !!tmp.length ? Math.random() < ((i / 50) * tmp.length || 1) : null
let parent_id = isChild ? Math.ceil(Math.random() * tmp.length - 1) : null
tmp.push({
id: i,
parent_id,
text: `Option ${i}`
})
}
// 2. Sort the generated data so child options are in order following their parent option.
this.items = tmp.reduce((items, item) => {
if (!items.length || !item.parent_id) {
items.unshift(item)
} else {
const index = items.findIndex(({ id }) => id === item.parent_id)
if (index) {
items.splice(index, 0, item)
}
}
return items
}, ).reverse()
},
filters: {
depth (option, items) {
let depth = 0
// 3. The magic happens here with a recursive function to find the depth to which each option is nested.
const pad = ({ parent_id }) => {
if (!!parent_id) {
depth += 1
let parent = items.find(({ id }) => id === parent_id)
if (!parent) {
return depth
}
return pad(parent)
}
return depth
}
// 4. Call the recursive function above, create an array of hyphens and concat them together with the option's text.
return Array(pad(option)).fill('-').concat([' ', option.text]).join('')
}
}
})<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<select v-model="selected">
<option v-for="option in items" :value="option.id" :key="option.id">{{ option | depth(items) }}</option>
</select>
<h4>Data</h4>
<ul>
<li v-for="item in items" :key="item.id"><pre><code>{{ item }}</code></pre></li>
</ul>
</div>add a comment |
I would use a filter and a recursive function to walk each option back until no parent is found, keeping tracking of the depth and using that to append the indentation marks.
Since you're likely passing the articles to a view file (in a PHP array or collection), you can pass the data to a vue component like:
<my-nested-select :articles='{!! json_encode($articles) !!}'></my-nested-select>
Here's an example using generated data, the filter being the important part:
new Vue({
el: '#app',
data: () => ({
items: ,
selected: null
}),
created () {
// 1. Create some dummy data where each option has an increasing chance of being nested.
const tmp =
for (let i = 1; i <= 50; i++) {
let isChild = !!tmp.length ? Math.random() < ((i / 50) * tmp.length || 1) : null
let parent_id = isChild ? Math.ceil(Math.random() * tmp.length - 1) : null
tmp.push({
id: i,
parent_id,
text: `Option ${i}`
})
}
// 2. Sort the generated data so child options are in order following their parent option.
this.items = tmp.reduce((items, item) => {
if (!items.length || !item.parent_id) {
items.unshift(item)
} else {
const index = items.findIndex(({ id }) => id === item.parent_id)
if (index) {
items.splice(index, 0, item)
}
}
return items
}, ).reverse()
},
filters: {
depth (option, items) {
let depth = 0
// 3. The magic happens here with a recursive function to find the depth to which each option is nested.
const pad = ({ parent_id }) => {
if (!!parent_id) {
depth += 1
let parent = items.find(({ id }) => id === parent_id)
if (!parent) {
return depth
}
return pad(parent)
}
return depth
}
// 4. Call the recursive function above, create an array of hyphens and concat them together with the option's text.
return Array(pad(option)).fill('-').concat([' ', option.text]).join('')
}
}
})<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<select v-model="selected">
<option v-for="option in items" :value="option.id" :key="option.id">{{ option | depth(items) }}</option>
</select>
<h4>Data</h4>
<ul>
<li v-for="item in items" :key="item.id"><pre><code>{{ item }}</code></pre></li>
</ul>
</div>add a comment |
I would use a filter and a recursive function to walk each option back until no parent is found, keeping tracking of the depth and using that to append the indentation marks.
Since you're likely passing the articles to a view file (in a PHP array or collection), you can pass the data to a vue component like:
<my-nested-select :articles='{!! json_encode($articles) !!}'></my-nested-select>
Here's an example using generated data, the filter being the important part:
new Vue({
el: '#app',
data: () => ({
items: ,
selected: null
}),
created () {
// 1. Create some dummy data where each option has an increasing chance of being nested.
const tmp =
for (let i = 1; i <= 50; i++) {
let isChild = !!tmp.length ? Math.random() < ((i / 50) * tmp.length || 1) : null
let parent_id = isChild ? Math.ceil(Math.random() * tmp.length - 1) : null
tmp.push({
id: i,
parent_id,
text: `Option ${i}`
})
}
// 2. Sort the generated data so child options are in order following their parent option.
this.items = tmp.reduce((items, item) => {
if (!items.length || !item.parent_id) {
items.unshift(item)
} else {
const index = items.findIndex(({ id }) => id === item.parent_id)
if (index) {
items.splice(index, 0, item)
}
}
return items
}, ).reverse()
},
filters: {
depth (option, items) {
let depth = 0
// 3. The magic happens here with a recursive function to find the depth to which each option is nested.
const pad = ({ parent_id }) => {
if (!!parent_id) {
depth += 1
let parent = items.find(({ id }) => id === parent_id)
if (!parent) {
return depth
}
return pad(parent)
}
return depth
}
// 4. Call the recursive function above, create an array of hyphens and concat them together with the option's text.
return Array(pad(option)).fill('-').concat([' ', option.text]).join('')
}
}
})<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<select v-model="selected">
<option v-for="option in items" :value="option.id" :key="option.id">{{ option | depth(items) }}</option>
</select>
<h4>Data</h4>
<ul>
<li v-for="item in items" :key="item.id"><pre><code>{{ item }}</code></pre></li>
</ul>
</div>I would use a filter and a recursive function to walk each option back until no parent is found, keeping tracking of the depth and using that to append the indentation marks.
Since you're likely passing the articles to a view file (in a PHP array or collection), you can pass the data to a vue component like:
<my-nested-select :articles='{!! json_encode($articles) !!}'></my-nested-select>
Here's an example using generated data, the filter being the important part:
new Vue({
el: '#app',
data: () => ({
items: ,
selected: null
}),
created () {
// 1. Create some dummy data where each option has an increasing chance of being nested.
const tmp =
for (let i = 1; i <= 50; i++) {
let isChild = !!tmp.length ? Math.random() < ((i / 50) * tmp.length || 1) : null
let parent_id = isChild ? Math.ceil(Math.random() * tmp.length - 1) : null
tmp.push({
id: i,
parent_id,
text: `Option ${i}`
})
}
// 2. Sort the generated data so child options are in order following their parent option.
this.items = tmp.reduce((items, item) => {
if (!items.length || !item.parent_id) {
items.unshift(item)
} else {
const index = items.findIndex(({ id }) => id === item.parent_id)
if (index) {
items.splice(index, 0, item)
}
}
return items
}, ).reverse()
},
filters: {
depth (option, items) {
let depth = 0
// 3. The magic happens here with a recursive function to find the depth to which each option is nested.
const pad = ({ parent_id }) => {
if (!!parent_id) {
depth += 1
let parent = items.find(({ id }) => id === parent_id)
if (!parent) {
return depth
}
return pad(parent)
}
return depth
}
// 4. Call the recursive function above, create an array of hyphens and concat them together with the option's text.
return Array(pad(option)).fill('-').concat([' ', option.text]).join('')
}
}
})<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<select v-model="selected">
<option v-for="option in items" :value="option.id" :key="option.id">{{ option | depth(items) }}</option>
</select>
<h4>Data</h4>
<ul>
<li v-for="item in items" :key="item.id"><pre><code>{{ item }}</code></pre></li>
</ul>
</div>new Vue({
el: '#app',
data: () => ({
items: ,
selected: null
}),
created () {
// 1. Create some dummy data where each option has an increasing chance of being nested.
const tmp =
for (let i = 1; i <= 50; i++) {
let isChild = !!tmp.length ? Math.random() < ((i / 50) * tmp.length || 1) : null
let parent_id = isChild ? Math.ceil(Math.random() * tmp.length - 1) : null
tmp.push({
id: i,
parent_id,
text: `Option ${i}`
})
}
// 2. Sort the generated data so child options are in order following their parent option.
this.items = tmp.reduce((items, item) => {
if (!items.length || !item.parent_id) {
items.unshift(item)
} else {
const index = items.findIndex(({ id }) => id === item.parent_id)
if (index) {
items.splice(index, 0, item)
}
}
return items
}, ).reverse()
},
filters: {
depth (option, items) {
let depth = 0
// 3. The magic happens here with a recursive function to find the depth to which each option is nested.
const pad = ({ parent_id }) => {
if (!!parent_id) {
depth += 1
let parent = items.find(({ id }) => id === parent_id)
if (!parent) {
return depth
}
return pad(parent)
}
return depth
}
// 4. Call the recursive function above, create an array of hyphens and concat them together with the option's text.
return Array(pad(option)).fill('-').concat([' ', option.text]).join('')
}
}
})<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<select v-model="selected">
<option v-for="option in items" :value="option.id" :key="option.id">{{ option | depth(items) }}</option>
</select>
<h4>Data</h4>
<ul>
<li v-for="item in items" :key="item.id"><pre><code>{{ item }}</code></pre></li>
</ul>
</div>new Vue({
el: '#app',
data: () => ({
items: ,
selected: null
}),
created () {
// 1. Create some dummy data where each option has an increasing chance of being nested.
const tmp =
for (let i = 1; i <= 50; i++) {
let isChild = !!tmp.length ? Math.random() < ((i / 50) * tmp.length || 1) : null
let parent_id = isChild ? Math.ceil(Math.random() * tmp.length - 1) : null
tmp.push({
id: i,
parent_id,
text: `Option ${i}`
})
}
// 2. Sort the generated data so child options are in order following their parent option.
this.items = tmp.reduce((items, item) => {
if (!items.length || !item.parent_id) {
items.unshift(item)
} else {
const index = items.findIndex(({ id }) => id === item.parent_id)
if (index) {
items.splice(index, 0, item)
}
}
return items
}, ).reverse()
},
filters: {
depth (option, items) {
let depth = 0
// 3. The magic happens here with a recursive function to find the depth to which each option is nested.
const pad = ({ parent_id }) => {
if (!!parent_id) {
depth += 1
let parent = items.find(({ id }) => id === parent_id)
if (!parent) {
return depth
}
return pad(parent)
}
return depth
}
// 4. Call the recursive function above, create an array of hyphens and concat them together with the option's text.
return Array(pad(option)).fill('-').concat([' ', option.text]).join('')
}
}
})<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<select v-model="selected">
<option v-for="option in items" :value="option.id" :key="option.id">{{ option | depth(items) }}</option>
</select>
<h4>Data</h4>
<ul>
<li v-for="item in items" :key="item.id"><pre><code>{{ item }}</code></pre></li>
</ul>
</div>edited Dec 30 '18 at 8:03
answered Dec 30 '18 at 6:39
DigitalDrifterDigitalDrifter
8,1852523
8,1852523
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53975228%2frecursively-display-dropdown-in-vue-js%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown