Using generic array name in template - javascript

I am really new to vue.js and HTML. I have two components that are working together. A photo-gallery and a tag-component. The tag-component uses the tags array to get the tags for a image. What i would like is to have a tag array for each image. I figured i could use the imageIndex and append that to the array name so I was string something like :tags=tags+imageIndex.
But if I do that, it does not work (i think it is not recognized as an array any more...) . My question is, is there a way to enter that in to the template, so that i have for each image an array with the name tags{index}?
Many thanks for the help!
Robin
<div id="SingleFile">
<button
id="refreshbtn"
class="btn btn-primary btn-margin"
#click="updateFileList">
refresh
</button>
<gallery :images="images" :index="index" #close="index = null"></gallery>
<div
:key="imageIndex"
:style="{ backgroundImage: 'url(' + image + ')', width: '300px', height: '200px' }"
#click="index = imageIndex"
class="image"
v-for="(image, imageIndex) in images"
>
<div>
<vue-tags-input
v-model="tag"
:tags="tags"
#tags-changed="newTags => tags = newTags"
/>
</div>
</div>
<div class="upload">
<upload-image url="http://localhost:8080/user" name="files" max_files="100"></upload-image>
</div>
</div>

You could use a method to achieve that:
<vue-tags-input
v-model="tag"
:tags="getTags(imageIndex)" ... >
and define it like :
methods:{
getTags(i){
return this['tags'+i];
}
}
by assuming that you have in your data object something like :
data(){
return{
tags0:[],
tags1:[],
...
}
}
or any property which has that syntax tags+index

Related

How to use iterativa data path in v-for loop (Vue)

I am a beginner of Vue
I would like to use my iterative image file name as "room1.jpg", "room2.jpg", "room3.jpg" ...
This is my code, the second line is the problem
<div v-for="(p,i) in products" :key="i">
<img src= "./assets/room"+str(i)+".jpg" class = "room-img">
<h4 #click="modelFlag = true">{{products[i]}}</h4>
<p>{{prices[i]}}</p>
<button #click="increase(i)">sign</button>
</div>
In Pyhton, I usually use for this
for i in range(number):
"./assets/room"+str(i)+".jpg"
Is there any similar way to this?
You've to bind variable data into your src as follow
<div v-for="(p,i) in products" :key="i">
<img :src="`./assets/room${str(i)}.jpg`" class = "room-img">
<h4 #click="modelFlag = true">{{products[i]}}</h4>
<p>{{prices[i]}}</p>
<button #click="increase(i)">sign</button>
You can perform/do above as follow too:
:src="'./assets/room'+str(i)+'.jpg'"
And it will works.
:src and v-bind:src work in same way
Reference
https://vuejs.org/api/built-in-directives.html#v-bind

Giving random background images to each div in the for loop in Vue Js

I have a v-for loop that runs on a div and gives out a bunch of tags. I need each of those tags to have a different src. Everything that I have tried so far results in all the tags getting the same source. Is there any way I can do this?
<div class="wrapper" v-for="result in results" :key="result.index">
<div class='small-card'>
<img class="thumbnail" :src="backgroundImage">
<div class="text-elements">
<span class="md-display-2 minicard-title">{{result.name}}</span>
<br class="break">
<span class="md-display-1 minicard-subtitle">{{result.state}}</span>
</div>
</div>
<br class="br3">
</div>
I recently did this in a project.
What I ended up doing was setting the style tag for background-image using the :style attribute.
Depending on how you are acquiring the image source, you will need to either create a method to return a random image URL, or access the image URL provided in the object. As you said "random" I assume the first approach would be the best fit.
Here's a very rough and untested example:
<template>
<div>
<div
v-for="index in 10"
:key="index"
:style="{'background-image': randomImage()}"
/>
</div>
</template>
<script>
export default {
name: 'Example',
data() {
return {
images: ['1.jpg', '2.jpg', '3.jpg', '4.jpg'],
};
},
methods: {
randomImage() {
return `url("${
this.images[Math.floor(Math.random() * this.images.length)]
}")`;
},
},
};
</script>
Make sure that the :style="{'background-image': randomImage()}" contains a () to ensure the method is called vs being referenced.

Conditionally hide the nth element of a v-for loop without modifying the array. vue 3 composition api search function

I have a ref variable (foxArticles ), which holds a list that contains 100 items. In a v-for loop i loop over each value. As a result, i have 100 values rendered on the page.
<template>
<div class="news_container">
<div
v-for="article in foxArticles"
v-bind:key="article"
class="article_single_cell"
>
<div
class="news_box shadow hover:bg-red-100 "
v-if="containsKeyword(article, keywordInput)"
>
<div class="news_box_right">
<div class="news_headline text-red-500">
<a :href="article.url" target="_blank">
{{ article.title }}
</a>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
const foxArticles = ref([]);
</script>
I also have a search function, which returns the value, if it includes the passed in keyword. The function is used in the child of the v-for loop.
<div class="search_input_container">
<input
type="text"
class="search_input"
v-model="keywordInput"
/>
</div>
<script>
const keywordInput = ref("");
function containsKeyword(article, keywordInput) {
if (article.title.toLowerCase().includes(keywordInput.toLowerCase())) {
return article;
}
}
</script>
The problem is, i can't use .slice() on the foxArticles array in the v-for loop, because that screws up the search functionality, as it returns only the values from the sliced range.
How can i have the access the all of the values of the array, while not rendering all 100 of returned articles on the initial load?
Any suggestions?
I think your approach will make it incredibly complex to achieve. It would be simpler to always iterate over some set, this set is either filtered based on a search-term, or it will be the first 100 items.
I'm not very familiar yet with the Vue 3 composition api so I'll demonstrate with a regular (vue 2) component.
<template>
<div class="news_container">
<div
v-for="article in matchingArticles"
v-bind:key="article"
class="article_single_cell"
>
... news_box ...
</div>
</div>
</template>
<script>
export default {
...
computed: {
matchingArticles() {
var articles = this.foxArticles;
if (this.keywordInput) {
articles = articles.filter(article => {
return this.containsKeyword(article, this.keywordInput)
})
} else {
// we will limit the result to 100
articles = articles.slice(0, 100);
}
// you may want to always limit results to 100
// but i'll leave that up to you.
return articles;
}
},
....
}
</script>
Another benefit is that the template does not need to worry about filtering results.
ok, so i kind of came up with another solution, for which you don't have to change the script part...
instead of having one v-for loop , you can make two of them, where each one is wrapped in a v-if statement div
The first v-if statement says, If the client has not used the search (keywordInput == ''), display articles in the range of (index, index)
The second one says = If the user has written something (keywordInput != ''), return those articles.
<template>
<div class="news_container">
<!-- if no search has been done -->
<div v-if="keywordInput == ''">
<div
v-for="article in foxArticles.slice(0, 4)"
v-bind:key="article"
class="article_single_cell"
>
<div class="news_box shadow hover:bg-red-100 ">
<div class="news_box_right">
<div class="news_headline text-red-500">
<a :href="article.url" target="_blank">
{{ article.title }}
</a>
</div>
</div>
</div>
</div>
</div>
<!-- if searched something -->
<div v-else-if="keywordInput != ''">
<div
v-for="article in foxArticles"
v-bind:key="article"
class="article_single_cell"
>
<div
class="news_box shadow hover:bg-red-100 "
v-if="containsKeyword(article, keywordInput) && keywordInput != ''"
>
<div class="news_box_right">
<div class="news_headline text-red-500">
<a :href="article.url" target="_blank">
{{ article.title }}
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
im not sure how this impacts performance tho, but that's a problem for another day

react js rendering images using props in url

I want to render images from my server ftp using props in React JS.
I have like:
render(){
console.log(this.props.product.image) //Which gives me the product image name properly
return(
<div className={this.props.openModal ? "modal-wrapper active" : "modal-wrapper"}>
<div className="modal" ref="modal">
<button type="button" className="close" onClick={this.handleClose.bind(this)}>×</button>
<div className="quick-view">
<div className="quick-view-image"><img src={`${this.props.product.image}`} alt={this.props.product.name +' image'}/></div>
<div className="quick-view-details">
<span className="product-name">{this.props.product.name}</span>
<span className="product-price">{this.props.product.price}</span>
</div>
</div>
</div>
</div>
)
}
In the log i am getting the image name, but why not the same in the img src attribute.
I tried to give the same line in src like i have given in console.
But just gave a try like:
Log data:
Ok i updated the full path, now image is rendering.
<img src={'http://localhost:5000/images/products/'+this.props.image}

angularjs ng-style: background-image isn't working

I'm trying to apply a background image to a div by using the angular ng-style ( I tried a custom directive before with the same behaviour ), but it doesn't seem to be working.
<nav
class="navigation-grid-container"
data-ng-class="{ bigger: isNavActive == true }"
data-ng-controller="NavigationCtrl"
data-ng-mouseenter="isNavActive = true; $parent.isNavActive = true"
data-ng-mouseleave="isNavActive = false; $parent.isNavActive = false"
data-ng-show="$parent.navInvisible == false"
data-ng-animate="'fade'"
ng-cloak>
<ul class="navigation-container unstyled clearfix">
<li
class="navigation-item-container"
data-ng-repeat="(key, item) in navigation"
data-ng-class="{ small: $parent.isNavActive, big: isActive == true }"
data-ng-mouseenter="isActive = true; isInactive= false"
data-ng-mouseleave="isActive = false; isInactive= true">
<div data-ng-switch on="item.id">
<div class="navigation-item-default" data-ng-switch-when="scandinavia">
<a class="navigation-item-overlay" data-ng-href="{{item.id}}">
<div class="navigation-item-teaser">
<span class="navigation-item-teaser-text" data-ng-class="{ small: isScandinavia }">{{item.teaser}}</span>
</div>
</a>
<span class="navigation-item-background" data-ng-style="{ 'background-image': 'public/img/products/{{item.id}}/detail/wide/{{item.images.detail.wide[0]}}' }"></span>
</div>
<div class="navigation-item-last" data-ng-switch-when="static">
<div class="navigation-item-overlay">
<div class="navigation-item-teaser">
<span class="navigation-item-teaser-text">
<img data-ng-src="{{item.teaser}}">
</span>
</div>
</div>
<span class="navigation-item-background">
<img class="logo" data-ng-src="{{item.images.logo}}">
</span>
</div>
<div class="navigation-item-default" data-ng-switch-default>
<a class="navigation-item-overlay" data-ng-href="{{item.id}}">
<div class="navigation-item-teaser">
<span class="navigation-item-teaser-text">{{item.teaser}}</span>
</div>
</a>
<span class="navigation-item-background" data-ng-style="{ 'background-image': 'public/img/products/{{item.id}}/detail/wide/{{item.images.detail.wide[0]}}' }"></span>
</div>
</div>
</li>
</ul>
</nav>
Though, if I do try a background color, it seems to be working fine. I tried a remote source and a local source too http://lorempixel.com/g/400/200/sports/, neither worked.
It is possible to parse dynamic values in a couple of way.
Interpolation with double-curly braces:
ng-style="{'background-image':'url({{myBackgroundUrl}})'}"
String concatenation:
ng-style="{'background-image': 'url(' + myBackgroundUrl + ')'}"
ES6 template literals:
ng-style="{'background-image': `url(${myBackgroundUrl})`}"
Correct syntax for background-image is:
background-image: url("path_to_image");
Correct syntax for ng-style is:
ng-style="{'background-image':'url(https://www.google.com/images/srpr/logo4w.png)'}">
IF you have data you're waiting for the server to return (item.id) and have a construct like this:
ng-style="{'background-image':'url(https://www.myImageplusitsid/{{item.id}})'}"
Make sure you add something like ng-if="item.id"
Otherwise you'll either have two requests or one faulty.
For those who are struggling to get this working with IE11
HTML
<div ng-style="getBackgroundStyle(imagepath)"></div>
JS
$scope.getBackgroundStyle = function(imagepath){
return {
'background-image':'url(' + imagepath + ')'
}
}
This worked for me, curly braces are not required.
ng-style="{'background-image':'url(../../../app/img/notification/'+notification.icon+'.png)'}"
notification.icon here is scope variable.
If we have a dynamic value that needs to go in a css background or
background-image attribute, it can be just a bit more tricky to
specify.
Let’s say we have a getImage() function in our controller. This
function returns a string formatted similar to this:
url(icons/pen.png). If we do, the ngStyle declaration is specified the
exact same way as before:
ng-style="{ 'background-image': getImage() }"
Make sure to put quotes around the background-image key name.
Remember, this must be formatted as a valid Javascript object key.
Just for the records you can also define your object in the controller like this:
this.styleDiv = {color: '', backgroundColor:'', backgroundImage : '' };
and then you can define a function to change the property of the object directly:
this.changeBackgroundImage = function (){
this.styleDiv.backgroundImage = 'url('+this.backgroundImage+')';
}
Doing it in that way you can modify dinamicaly your style.
The syntax is changed for Angular 2 and above:
[ngStyle]="{'background-image': 'url(path)'}"

Categories

Resources