Trying to pass url in vue and add API string after - vue.js

I'm looking to enter an image url in a text field, then have that url be displayed in an image tag but also have that original url modified by adding an API string at the end.
Here is the js:
Vue.component('imagesinstagram', {
props: ['url'],
template: `
<div class="container imgix-cell">
<img class="img-variant" :src="url + '?q=60'"/>
<div class="subtext">
<br>Instagram
</div>
</div>
`
})
new Vue({
el: '#app_images',
data: function() {
return {
myUrl: '',
comparisons: [
{ id: 1, url: 'myUrl' }
]
}
}
})
Now here is the html:
<input type="text" placeholder="Enter imgix URL" v-model="myUrl"/>
<div>Entered URL: {{ myUrl }} </div>
</div>
<div class="container">
<imagesinstagram
v-for="comparison in comparisons"
v-bind:url="comparison.url"
></imagesinstagram>
</div>
So essentially I enter an image url as a text field, it is returned as myUrl. Then I am trying to use my vue component to call that same url but add ?q=60 afterwards as a query string.
It is just returning this in my codepen: https://cdpn.io/boomboom/v2/myUrl?q=60 . the myUrl should be the actual image url I entered.

Ok there are a few problems and I don't understand what you are trying to do with 'comparisons'. For starters, in your components you only have access to the component's props. So you have 'url' and not 'myUrl' ( which is only available in the parent component).
Then, in your data, you can't reference other parts of your data. When you say { id: 1, url: 'myUrl' }, url will just be the literal string 'myUrl'. This is not what you want.
I've made the changes and I think this is doing what you mean, but I don't have imgix.

Related

VueJS Axios API, trying to get only 1 result, not many

I'm trying to get only 1 response from the Nasa images API using VueJS and Axios. I've followed the tutorial here(https://www.youtube.com/watch?v=GiIQce7Rx4Y&t=939s) and the app is working just like shown. But this tutorial shows how to get the complete list of images available through this API, I only want the first image but can't figure out how.
Here's the code for the api component:
<template>
<div class="search">
<section id="sectionB">
<h2>Type in your search term</h2>
<form v-on:submit.prevent="getResult(query)">
<input type="text" placeholder="Type in your search" v-model="query" />
</form>
<br/>
<div v-if="results">
<div v-for="result in results" v-bind:key="result">
<img v-bind:src="result.links[0].href" class="imgContainer" />
</div>
</div>
</section>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "search",
data() {
return {
msg: "Search",
query: "",
results: "",
};
},
methods: {
getResult(query) {
axios.get(
"https://images-api.nasa.gov/search?q=" + query + "&media_type=image"
)
.then((response) => {
console.log(response.data.collection.items);
this.results = response.data.collection.items;
});
},
},
};
</script>
I tried removing f-for to stop the loop but that removed all images, not just everyone after the first.
You should refer to the documentation of the API on the website of Nasa: https://images.nasa.gov/docs/images.nasa.gov_api_docs.pdf. The only endpoint they have that returns images is the search endpoint that you are using.
However, reading your question again.. You can just show the first of the list (array) of results: results[0], like below:
<div v-if="results">
<img v-bind:src="results[0].links[0].href" class="imgContainer" />
</div>

How to render HTML from a property of items being displayed with v-for loop?

I send an array of objects which each have a .html property that has HTML text in it, e.g. <h1>...</h1> or <h2>...</h2>
I want to have the HTML from each item display one after another in the DOM, like this:
<h1>...</h1>
<h2>...</h2>
<h2>...</h2>
<h1>...</h1>
<h2>...</h2>
However, all of these attempts do not work:
<div v-for="item in outlineItems" v-html="item.html"></div>
displays HTML wrapped in divs: <div><h1>...</h1></div> and <div><h2>...</h2></div>
<template v-for="item in outlineItems" v-html="item.html"></template>
displays nothing
<template v-for="item in outlineItems">{{item.html}}</template>
displays the literal HTML instead of rendering it
<template v-for="item in items"><template v-html="item.html"></template></template>
displays nothing
How can I simply display the contents of the .html property of each item so that the HTML in it renders, without any wrapping elements on it?
You could do it using a single wrapper element for the whole lot by concatenating all the HTML in a computed property:
new Vue({
el: '#app',
data () {
return {
outlineItems: [
{ html: '<h1>Heading 1</h1>' },
{ html: '<h2>Heading 2</h2>' },
{ html: '<h3>Heading 3</h3>' }
]
}
},
computed: {
outlineHtml () {
return this.outlineItems.map(item => item.html).join('')
}
}
})
<script src="https://unpkg.com/vue#2.6.11/dist/vue.js"></script>
<div id="app">
<div v-html="outlineHtml"></div>
</div>
Behind the scenes v-html sets the innerHTML of its corresponding DOM node. A <template> tag doesn't create a DOM node so the innerHTML can't be set anywhere.
I would add that v-html is considered an 'escape hatch'. Where possible you should avoid using it and let Vue create the HTML itself. Generally the approach would be to use a suitable data structure to hold the data (rather than a blob of markup) and then render that data structure within the template.
One possible solution is to create multiple unique components. You can even pass in props, and there are no wrappers
Vue.component('greeting', {
template: '<h1>Welcome to coligo!</h1>'
});
Vue.component('titles', {
template: '<h1>title 1</h1>'
});
Vue.component('title2', {
template: '<h2>Welcome to coligo!</h2>'
});
Vue.component('title3', {
template: '<h3>{{text}}</h3>',
props: ['text']
});
var vm = new Vue({
el: '#app',
data: {
items: [
{ type: 'greeting' },
{ type: 'titles' },
{ type: 'title2' },
{ type: 'title3', text: 'test' }
]
}
});
<script src="https://unpkg.com/vue#2.6.11/dist/vue.js"></script>
<div id="app">
<component v-for="(item,i) in items" :is="item.type" :text="item.text" :key="i"></component>
</div>

Get parameter from input element but how to use in vue.js?

I known how to get value from input element.
<div id="app-6">
<p>{{ url }}</p>
<input v-model="url">
</div>
<script>
new Vue({
el: '#app-6',
data: {
url: ''
}
})
</script>
And I want to use url variable to get page like this:
<div id="app-6">
<input v-model="url">
<input type="submit" v-on:click="open">
<p>{{ result }}</p>
</div>
<script>
new Vue({
el: '#app-6',
data: {
url: '',
result: ''
},
methods : {
open: function (data) {
var url = data.url
this.$http.get('http://httpbin.org/ip', (data) => {
this.result = data.origin
}).error(function (data, status, request) {
//handler error
})
}
}
})
</script>
But it doesn't work. The url variable is null. In console, it print like this:
Access to XMLHttpRequest at 'file:///D:/serialshow/vuetest.html' from
origin 'null' has been blocked by CORS policy: Cross origin requests
are only supported for protocol schemes: http, data, chrome, chrome-
extension, https.
Vue version: 2.5.17
You are not sending data to open method, but I suggest to use this.url to get value inside method
Either use
open: function () {
var url = this.url;
Run your application in any local server instead directly from D drive

How to handle when VueJS computed properties return HTML code?

I use VueJS 2 to render and calculate form items. Now I need to show a number if a propertie is under 10, and I need show a text message if the propertie is over or equal 10.
I use this code:
Vue.component('mycomponent', {
template: '#mytemp',
data: function() {
// ...
},
computed: {
mycomputedprop: function() {
if (this.model_a < 10) {
return '<span class="numbervalue">' + this.model_a + '€</span>';
} else {
return '<span class="textvalue">I\'ll contact you as soon as possible!</span>';
}
}
}
});
I use this code to show the value:
<div id="app">
{{ mycomputedprop }}
</div>
The problem is: if I show this value it shows the HTML code as text, not as HTML. How can I show the returned value as a HTML code?
You could use v-html
Document : Raw-HTML
<div id="app">
<div v-html="mycomputedprop"></div>
</div>
The contents of this div will be replaced with the value of the
rawHtml property, interpreted as plain HTML - data bindings are
ignored. Note that you cannot use v-html to compose template partials,
because Vue is not a string-based templating engine. Instead,
components are preferred as the fundamental unit for UI reuse and
composition.
Vue 3 Example:
const RenderHtmlApp = {
data() {
return {
rawHtml: '<span style="color: red">This should be red.</span>'
}
}
}
Vue.createApp(RenderHtmlApp).mount('#example1')
<script src="https://unpkg.com/vue#next"></script>
<div id="example1">
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
</div>
Assuming that modal_a is defined in the data of your component, why not handle this within the component template?
<div id="app">
<span v-if="model_a < 10" class="numbervalue">{{model_a}} €</span>
<span v-else class="textvalue">I\'ll contact you as soon as possible!</span>
</div>

Wrap element using v-if, otherwise just have content itself

I have a set of elements being generated in a v-for directive that, if the object has a url property, get wrapped in an <a> tag - otherwise, I need it to just emit the element itself.
For example,
var data = {
events: [
{name: "Foo"},
{name: "Bar", url: "google.com"}
]
};
and the corresponding HTML:
<div v-for="event in events">
<span>{{event.name}}</span>
</div>
What I need is to wrap the <span> in an <a v-bind:href="url"> only if there is a url property present.
I understand I could use a v-if and use two spans, such as:
<span v-if="!event.url">{{event.name}}</span>
<a v-bind:href="event.url" v-if="event.url">
<span>{{event.name}}</span>
</a>
However, in my use case the <span> element here could be massive and I don't want to repeat myself just to wrap the element.
Is there a way to achieve a conditional wrap such as the above?
You can use v-html for example and render your logic inside a function:
function wrapSpan(el, link) { // link wrapper function
return `${el}`;
}
new Vue({
el: '#app',
data: {
events: [
{name: "Foo"},
{name: "Bar", url: "google.com"}
]
},
methods: {
element: function(i) {
const name = this.events[i].name;
const url = this.events[i].url || null;
const span = `<span style="color: green">${name}</span>`; // long span
return (url) ? wrapSpan(span, url) : span;
}
}
});
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<div v-for="(event, index) in events">
<span v-html="element(index)"></span>
</div>
</div>