I have array of objects that includes name and description. My goal here is to display the name and description dynamically in my image carousel with the help of Tiny Slider js.
I try the following attempt but failed.
Use .getElementById() to get the slider element and .map() to render the data inside the object but unfortunately the whole data was rendered in one slider only.
The actual result:
index.html
<div id="sliderCont" class="my-slider">
<div>
<div class="slide">
<div class="slide-img" style="background-image: url('src/images/img-1.jpg')">
View More
</div>
<br>
<div class="slide-info">
<h3 id="project-name"></h3>
<p id="project-description" class="subtext"></p>
</div>
</div>
</div>
</div>
app.js
const project = [
{
image: "",
name: "Project 1",
description: "Project Description here.",
},
{
image: "",
name: "Project 2",
description: "Project Description here. 2",
},
{
image: "",
name: "Project 3",
description: "Project Description here. 3",
},
{
image: "",
name: "Project 4",
description: "Project Description here. 4",
},
];
document.getElementById("project-name").innerHTML = project.map((proj) => proj.name);
document.getElementById("project-description").innerHTML = project.map((proj) => proj.description);
Tiny Slider Config
let slider = tns({
container: ".my-slider",
slideBy: 1,
speed: 200,
nav: false,
controlsContainer: "#controls",
prevButton: ".previous",
nextButton: ".next",
preventScrollOnTouch: "auto",
autoplay: true,
autoplayButtonOutput: false,
responsive: {
1600: {
items: 4,
gutter: 20,
},
1024: {
items: 3,
gutter: 20,
},
768: {
items: 2,
gutter: 20,
},
480: {
items: 1,
},
},
});
project.map((proj) => proj.name)
...returns an array:
["Project 1", "Project 2", "Project 3", "Project 4"]
When assigning this array to document.getElementById("project-name").innerHTML it is converted to the string "Project 1,Project 2,Project 3,Project 4".
So you're essentially assigning this string to the .project-name innerHTMLvalue:
document.getElementById("project-name").innerHTML = "Project 1,Project 2,Project 3,Project 4";
The same thing happens with:
document.getElementById("project-description").innerHTML = project.map(
(proj) => proj.description
);
Instead, first iterate, forEach(), over the project array, and in the loop block add a slide.
To create multiple slides use cloneNode() to copy the .slide DIV. (Since you're duplicating this DIV and it's child nodes, don't use IDs. Use class names instead: .project-name and .project-description.) And append the new node to the .slide's parentNode.
After the project array loop is exited, remove, removeChild(), the original .slide-info DIV.
const project = [
{
image: "https://source.unsplash.com/random?w=200",
url: "p1.html",
name: "Project 1",
description: "Project Description here."
},
{
image: "https://source.unsplash.com/random?w=200",
url: "p2.html",
name: "Project 2",
description: "Project Description here. 2"
},
{
image: "https://source.unsplash.com/random?w=200",
url: "p3.html",
name: "Project 3",
description: "Project Description here. 3"
},
{
image: "https://source.unsplash.com/random?w=200",
url: "p4.html",
name: "Project 4",
description: "Project Description here. 4"
},
];
// get target DIV, containing .slide-img, .project-url, .project-name, and .project-description
const slide = document.querySelector(".slide");
// iterate over project array
project.forEach(proj => {
// make a clone of .slide for new slide
const newslide = slide.cloneNode(true);
// add image background to .slide-img div
newslide.querySelector(".slide-img").style.backgroundImage = `url('${proj.image}')`;
// add url href to .project-url anchor tag
newslide.querySelector(".project-url").href = proj.url;
// add name to .project-name header
newslide.querySelector(".project-name").innerHTML = proj.name;
// add description to .project-description paragraph
newslide.querySelector(".project-description").innerHTML = proj.description;
// add slide to .slide parent
slide.parentNode.appendChild(newslide);
});
// remove original slide
slide.parentNode.removeChild(slide);
<div>
<div class="slide">
<div class="slide-img">
<a class="project-url" href="" style="color: white;">View More</a>
</div>
<br>
<div class="slide-info">
<h3 class="project-name"></h3>
<p class="project-description subtext"></p>
</div>
</div>
</div>
Related
I have an array of songs and inside the template I have an icon to toggle between show/hide of a div. It works when clicked and it expands the div but it expands the div for every item in the array (no matter which song is clicked). I would like it to only expand the div of the clicked item. Do I need to link it the id variable somehow? Here is the code:
This is in the html template:
<div class="dropdown-icon" title="Show/Hide Description"
#click="toggleShowDescription">
<i class="icon ion-ios-arrow-dropdown-circle"></i>
</div>
<div :class="showDescription?'show':'hide'" v-if="showDescription">
<p class="song-description">{{song.description}}</p>
This what I have in the JS concerning the hide/show div element:
songs: [
{
id: 1,
title: "Track 1",
description: "Description 1",
url: "",
keywords:"",
genre:"",
moods:"",
tempo:"",
theme:"",
},
{
id: 2,
title: "Track 2",
description: "Description 2",
url:"",
keywords: "",
genre:"",
moods:"",
tempo:"",
theme:"",
},
],
showDescription: false,
},
methods: {
toggleShowDescription() {
this.showDescription = !this.showDescription;
},
},
You are using the value of showDescription for every single song. The best bet would be to create an array that tracks which song descriptions are showing and then add/remove items as the toggle button is clicked.
For the template...
<div class="dropdown-icon" title="Show/Hide Description"
#click="toggleShowDescription(song)">
<i class="icon ion-ios-arrow-dropdown-circle"></i>
</div>
<div :class="showDescription?'show':'hide'" v-
if="songsDisplayingDescription.indexOf(song.id) !== -1">
<p class="song-description">{{song.description}}</p>
and then the script...
songsDisplayingDescription: [],
},
methods: {
toggleShowDescription(song) {
const songId = song.id;
const indexOfSongId = this.songsDisplayingDescription.indexOf(songId);
if (indexOfSongId !== -1) {
this.songsDisplayingDescription.splice(indexOfSongId, 1);
return;
}
this.songsDisplayingDescription.push(songId);
}
}
I am trying to map over array of objects which each array contains another nested array of objects. However, the map does not work on the nested array. How do I map over the contents of the nested array while keeping all the content under the same title of the parent object?
Fiddle: https://jsfiddle.net/69z2wepo/249197/
The data structure looks like:
[
{
title: "title1",
content: [
{
imageUrl: "http://placehold.it/300x300",
title: "Campaigns",
description:
"Short description explaining the use of this design in a single sentence."
},
{
imageUrl: "http://placehold.it/300x300",
title: "Events",
description:
"Short description explaining the use of this design in a single sentence."
},
{
imageUrl: "http://placehold.it/300x300",
title: "General",
description:
"Short description explaining the use of this design in a single sentence."
}
]
},
{
title: "title2",
content: [
{
imageUrl: "http://placehold.it/300x300",
title: "Video Template A",
description:
"Short description explaining the use of this design in a single sentence."
},
{
imageUrl: "http://placehold.it/300x300",
title: "Video Template A",
description:
"Short description explaining the use of this design in a single sentence."
}
]
}
];
The map looks like
{dataItems.map((item, index) => {
return (
<h1>{item.title}</h1>
// for each item, loop over the content array objects
<img src={item.content.imageUrl} />
<h3>{item.content.title}</h3>
<h3>{item.content.description}</h3>
<hr />
);
})}
Since each element has a content array, you must map over content as well.
Example
{dataItems.map((item, index) => (
<div key={index}>
<h1>{item.title}</h1>
{item.content.map((c, i) => (
<div key={i}>
<img src={c.imageUrl} />
<h3>{c.title}</h3>
<h3>{c.description}</h3>
<hr />
</div>
))}
</div>
))}
This is a working example.
const dataItems = [{
title: "title1",
content: [{
imageUrl: "http://placehold.it/300x300",
title: "Campaigns",
description: "Short description explaining the use of this design in a single sentence."
},
{
imageUrl: "http://placehold.it/300x300",
title: "Events",
description: "Short description explaining the use of this design in a single sentence."
},
{
imageUrl: "http://placehold.it/300x300",
title: "General",
description: "Short description explaining the use of this design in a single sentence."
}
]
},
{
title: "title2",
content: [{
imageUrl: "http://placehold.it/300x300",
title: "Video Template A",
description: "Short description explaining the use of this design in a single sentence."
},
{
imageUrl: "http://placehold.it/300x300",
title: "Video Template A",
description: "Short description explaining the use of this design in a single sentence."
}
]
}
];
class App extends React.Component {
render() {
return <div>
{
dataItems.map((item, index) => {
return ( <div>
<h1>{item.title}</h1>
{ item.content.map((c, i) => <div>
<h3>{c.title}</h3>
<h3>{c.description}</h3>
</div>)}
</div>
)
})
}
</div>
}
}
ReactDOM.render( < App / > , document.getElementById('root'));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
Been trying to figure out how to do the dynamic list or menu with the JSON data format below:
modules: [
{
module_id: 1,
module_parent_id: 0,
module_name: "Module 1",
status: true,
child:
[
{
module_id: 2,
module_parent_id: 1,
module_name: "Module 2",
status: true,
child:
[
{
module_id: 3,
module_parent_id: 1,
module_name: "Module 3",
status: true,
},
{
module_id: 4,
module_parent_id: 1,
module_name: "Module 4",
status: true,
},
]
},
{
module_id: 5,
module_parent_id: 1,
module_name: "Module 5",
status: true,
},
]
},
{
module_id: 6,
module_parent_id: 0,
module_name: "Module 6",
status: false
}
]
}
},
Already tried using v-for but it's not dynamic:
<ul v-for="module in modules">
<li>
{{module.module_name}}
</li>
<ul v-for="module_child in module.child" v-if="module.child">
<li>
{{module_child.module_name}}
</li>
<ul v-for="module_sub_child in module_child.child" v-if="module_child.child">
<li>
{{module_sub_child.module_name}}
</li>
</ul>
</ul>
</ul>
**NOTE: I need to use v-for instead of creating a method since I am using Vue-JS toggle button plugin: https://github.com/euvl/vue-js-toggle-button. It doesn't render the plugin when I tried to do the method. (If there's no other way in doing this, maybe I'll do my own custom toggle-button..)
Here is the expected output for reference.
If plugin is not working, its either you forgot to add Vue.use(ToggleButton)) before using it or you are trying to place it inside your template directly.
For other components to work inside your own you must initialize
it like this
import ToggleButton from 'vue-js-toggle-button'
export default {
data: function () { . . . },
components: {
'toggle-button': ToggleButton,
},
template: `
<ul v-for="module in modules">
<li>
<toggle-button #change="onChangeEventHandler"/>
</li>
</ul>`
}
I have a javascript array with a lot of object, like so:
var myArray = [
{
"id": 1,
"name": "Name 1",
"active": false
},{
"id": 2,
"name": "Name 2",
"active": true
},{
"id": 3,
"name": "Name 3",
"active": false
}
]
I use the id parameter of these objects to compare them and store values. To get the object that belongs to that id, I have written a filter:
getTest: function(id){
var result = this.tests.filter(function(o){return o.id == id;} );
return result ? result[0] : null;
}
So I can easily use this filter inline. Now I'd like to get properties of the filtered result inline as well, for example:
<template if="{{ { id | getTest }.active">
You are active!
</template>
However doing this leads to an invalid expression. I've read through the docs multiple times, but don't quite see if this is even possivle.
How can I do this?
You can make a custom filter with an id parameter. That filter will take the item, verify if it has the good id, and the verify if it's active or not.
My original example was in this Plunker http://plnkr.co/edit/FSwzndyjRxJIymehsZIg?p=preview
Hope it helps! If it isn't exactly what you wanted to do, please ask, I'll try to answer further :)
[EDIT]
OK, after reading your comments, how about this:
<template is="auto-binding">
<h1>Hi !</h1>
<template repeat="{{item in myArray}}">
<template if="{{ item.active }}">
<p>
Item id:{{item.id}} is active! <br>
Amount of steps in this test: {{ item.steps }} <br>
Test description: {{ item.description }}
</p>
</template>
</template>
</template>
<script>
var template = document.querySelector('template[is="auto-binding"]');
template.count=0;
template.myArray = [
{
"id": 1,
"name": "Name 1",
"active": false,
"steps": 3,
"description": "Lorem"
},{
"id": 2,
"name": "Name 2",
"active": true,
"steps": 4,
"description": "Ipsum"
},{
"id": 3,
"name": "Name 3",
"active": true,
"steps": 5,
"description": "Lorem Ipsum"
}
];
</script>
Then you get the output you want:
Item id:2 is active!
Amount of steps in this test: 4
Test description: Ipsum
Item id:3 is active!
Amount of steps in this test: 5
Test description: Lorem Ipsum
The Plunker is http://plnkr.co/edit/nBYeeZ2Uw0EFihAhNYpl?p
I have 2 same dynatrees in the same page as shown in this js fiddle http://jsfiddle.net/37ppf/3/.
$("#tree1").dynatree({
onSelect : function(select,node){},
checkbox: true,
children: [
{title: "Item 1",key:"1"},
{title: "Folder 2", isFolder: true, key:"2",
children: [
{title: "Sub-item 2.1", },
{title: "Sub-item 2.2", }
]
},
{title: "Item 3",key:"5"}
]
});
$("#tree2").dynatree({
onSelect : function(select,node){},
checkbox: true,
children: [
{title: "Item 1",key:"1"},
{title: "Folder 2", isFolder: true, key:"2",
children: [
{title: "Sub-item 2.1", },
{title: "Sub-item 2.2", }
]
},
{title: "Item 3",key:"5"}
]
});
<div id="tree1"> </div>
<div id="tree2"> </div>
Now When a user selects any node in any of the dynatree I want to get the div id in which the tree from which the user has selected the node is loaded.i.e if user selects from first tree I want to get output as tree1(div id) and if a node is selected from second tree i want to get tree2. Is this possible. I tried
$(this).closest(".dynatree-container").parent("div").attr("id")
But its coming undefined.
It feels super hacky, but you can do it this way:
onSelect : function(select,node){
alert(node.tree.$tree[0].id);
},
node.tree.$tree[0] will return the javascript object of its parent tree.
See the working code at
JSFiddle
Try this
$(document).on('click','span',function(){
console.log($(this).parents('div').attr('id'))
})
DEMO