In my style block I have code like this
<style lang="scss">
.item {
background: url('~#assets/images/i10.png');
}
</style>
As per my specific needs I need to load the image from the javascript variable thats being injected in html page. e.g in index.html file coming up from server it could be
itemURL = '/abc/def/def/img.png';
Something like:
<style lang="scss">
.item {
background: url([window.itemURL);
}
</style>
and then I need to use that url as background image of item.
I can't use document.getElementBy(xyz) as item is loading/unloading dynamically into DOM.
Note: Its vuejs project created via vue command line tools
u can use img tag instead of css style
<template>
<div>
<img
:src="url"
>
</div>
</template>
<script>
export default {
data() {
return {
url: null
}
},
mounted() {
this.url = injectImageUrl() // js function to inject url
}
}
</script>
Maybe you can use props? But I don't think it's possible to access the props from inside the style tag. The only way to do this is by using inline styling.
<template>
<div :style={ backgroundImage: 'url('+ imgUrl +')' }>
</div>
</template>
<script>
export default {
props: {
imgUrl: {
type: String,
}
},
}
</script>
Related
I've created a component that stores an iframe
<template>
<iframe height=1000 width=100% :src="full" #myEvent="thisMethod" ></iframe>
</template>
<script>
export default {
data() {
return {
path: '../lib/pdfjs-2.7.570-dist/web/viewer.html',
name:'../t1.pdf',
full: '../lib/pdfjs-2.7.570-dist/web/viewer.html?file=pdfs/t1.pdf'
};
},
props: {
fileName: String,
path:String
},
methods:{
thisMethod(){
console.log("Hello from Parent")
}
}
}
</script>
<style scoped>
div {
width: 50%;
height: 79vh;
min-width: 400px;
}
</style>
Inside my viewer.html I want to fire an Event to my parent so that 'thisMethod' would be called.
I've tried doing:
<html>
A lot of HTML tags
</html>
<script>
function myfunction(data){
this.$emit('myEvent',data)
}
</script>
but viewer is a html page and I can't seem to find a way to send an event from a .html file to a .Vue file.
My question is basically what would be a solution to be able to handle a JavaScript event in a HTML page inside a .vue parent page ?
I have a CRUD that enables me to write Vue.js component's code in the textarea like:
<template>
<div><p class='name-wrapper'>{{ model.name }}</p></div>
</template>
<script>
module.exports = {
name: 'NameWrapper',
props: ['model']
}
</script>
<style lang='sass'>
.name-wrapper
color: red
</style>
Then in other component, I fetch this data and want to register it as a dynamic/async, custom component like:
<template>
<component :is='dynamicName' :model='{name: "Alex"}'></component>
</template>
<script>
import httpVueLoader from 'http-vue-loader'
import Vue from 'vue'
export default {
name: 'DynamicComponent',
props: ['dynamicName', 'componentDefinitionFromTextareaAsString'],
beforeCreate: {
// I know that as a second parameter it should be an url to the file, but I can't provide it, but I would like to pass the contents of the file instead there:
httpVueLoader.register(Vue, this.$options.propsData.componentDefinitionFromTextareaAsString)
// I was trying also:
Vue.component(this.$options.propsData.dynamicName, this.$options.propsData.componentDefinitionFromTextareaAsString)
}
}
</script>
As far as I know, httpVueLoader needs the url to the .vue file instead - is there a way to pass there the code itself of the component?
I am aware that passing and evaluating <script></script> tag contents can cause security issues, but I really need to do it that way.
I've read also about Vue.js compile function, but that works only for templates, not the code of the component (so the script tags again).
Is it even possible to achieve such functionality in Vue.js?
It should be possible to use a data: URI with http-vue-loader, like this:
const vueText = `
<template>
<div class="hello">Hello {{who}}</div>
</template>
<script>
module.exports = {
data: function() {
return {
who: 'world'
}
}
}
<\/script>
<style>
.hello {
background-color: #ffe;
}
</style>
`
const MyComponent = httpVueLoader('data:text/plain,' + encodeURIComponent(vueText))
new Vue({
el: '#app',
components: {
MyComponent
}
})
<script src="https://unpkg.com/vue#2.6.10/dist/vue.js"></script>
<script src="https://unpkg.com/http-vue-loader#1.4.1/src/httpVueLoader.js"></script>
<div id="app">
<my-component></my-component>
</div>
If that doesn't work for some reason (maybe because one of your target browsers doesn't support it) then you could get it working by patching httpRequest. See https://www.npmjs.com/package/http-vue-loader#httpvueloaderhttprequest-url-. The documentation focuses on patching httpRequest to use axios but you could patch it to just resolve the promise to the relevant text.
I believe this is a relatively unique problem, and as such I'm having difficulty trying to solve it.
I'm creating a file manager-like solution in Vue, and I'm looking for certain folders/files to display a unique thumbnail (in my example, showing the Creative Cloud logo if the 'Creative Cloud' folder is found). In my app I am using a component to represent each file.
The file-grid Vue file reads as such (sorry for the mess, I've been trying to integrate multiple different solutions to see what sticks):
<template>
<div id="localMain">
<div id="filesGrid">
<File :fileName="file"
:imageAddress="findImage($event)"
id="file"
v-for="file in files"
:key="file.id"></File>
</div>
</div>
</template>
<script>
import File from './LocalMain/File';
export default {
data() {
return {
creativeCloud: 'static/logos/creative-cloud.svg',
blankThumb: 'static/code.svg',
files: [
'Creative Cloud',
'Documents',
...
],
};
},
components: {
File,
},
methods: {
findImage: function findImage(e) {
/* Get the name of the file/folder, and choose a thumbnail accordingly */
const name = e.target.dataset.fileName;
let image = this.blankThumb;
if (name === 'Creative Cloud') {
image = this.creativeCloud;
} else {
image = this.blankThumb;
}
return image;
},
},
};
</script>
<style scoped>
/* styling */
</style>
The file component itself looks like this:
<template>
<div id="file">
<img :src="imageAddress" alt="Logo" id="fileImg" />
<h3 v-if="display">{{ fileName }}</h3>
</div>
</template>
<script>
export default {
data() {
return {
display: false,
};
},
props: {
fileName: String,
imageAddress: String,
},
};
</script>
<style scoped>
/* styling */
</style>
I apologise for the ambiguity in this question, but I'm quite confused.
I might be missing something, but why not just v-bind the method with the file name as the argument?
eg.
Parent template
<File :fileName="file"
:imageAddress="findImage(file)"
id="file"
v-for="file in files"
:key="file.id"></File>
Parent Javascript
findImage: function findImage(name) {
var image = this.blankThumb;
if (name === 'Creative Cloud') {
image = this.creativeCloud;
}
return image;
},
I would like to dynamically update styles inside style tags.
However creating a container model for Vue, removes the style tags.
I know style tags should belong in the head of the page, but this is just for the sake of ease of use.
So what I would like to have is a wrapper with an element and style tags inside:
<div class="setting">
<style>
.setting input {
background: {{bgColor}};
}
</style>
<input class="setting" type="text" v-model="bgColor">
</div>
The value from the input should update the value of the css style.
Whenever done with simple div elements this works, but style tags seem to be a problem
The javascript set up is the following:
new Vue({
el: '.setting',
data: {
bgColor: 'red'
}
});
However when the style tags have a specific id, this could work, but I can't bind it to an input field.
<style id="setting">
#blue {
background: {{bg}}
}
#blue:hover {
background: {{bgHover}}
}
</style>
<div id="blue"></div>
and the js:
new Vue({
el: '#setting',
data: {
bg: 'blue',
bgHover: 'red'
}
});
Can someone help me understand how I can achieve updating values between style tags.
jsfiddle set up
Thanks.
Here's what I think is a good workaround/solution.
It is just a custom component, so it's as reusable as it gets. All of Vue's goods like v-if can all be used.
Another pro is that the styles generated will be there only as long as the component is!
Vue.component('v-style', {
render: function (createElement) {
return createElement('style', this.$slots.default)
}
});
// demo usage, check the template
new Vue({
el: '#app',
data: {
bgColor: 'red'
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app" class="stuff">
<v-style>
.stuff input {
background: {{bgColor}};
}
</v-style>
Remove "red" and type "yellow":
<input class="setting" type="text" v-model="bgColor">
</div>
The one drawback I see is that since the name of the tag is <v-style> (or whatever you chose to call it) and not <style>, the IDEs may not color it nicely. But otherwise it'll just be like a regular <style> tag.
Standard solution: using v-bind:style
This doesn't modify style tags, but the standard way of setting styles is using object style bindings.
Basically you'd use a :style attribute and assign to it the CSS properties of the style in the form of an object. Demo below.
new Vue({
el: '.setting',
data: {
bgColor: 'red'
},
computed: {
inputStyles() {
return {
background: this.bgColor
}
}
}
});
<script src="https://unpkg.com/vue"></script>
<div class="setting">
Remove "red" and type "yellow":
<input class="setting" type="text" v-model="bgColor" :style="inputStyles">
</div>
vue-loader (and Vue template compiler Vue.compile(..)) both will filter out any <style> tags that are encountered in the template.
A simple solution to get around this, is to take advantage of Vue's built-in<component> component.
<template>
<div>
<component is="style">
.foo[data-id="{{ uniqueId }}"] {
color: {{ color }};
}
.foo[data-id="{{ uniqueId }}"] .bar {
text-align: {{ align }}
}
</component>
<div class="foo" :id="id" :data-id="uniqueId">
<div class="bar">
</div>
</div>
</div>
</template>
<script>
export default {
props: {
id: {
type: String,
default: null
}
},
computed: {
uniqueId() {
// Note: this._uid is not considered SSR safe though, so you
// may want to use some other ID/UUID generator that will
// generate the same ID server side and client side. Or just
// ensure you always provide a unique ID to the `id` prop
return this.id || this._uid;
},
color() {
return someCondition ? 'red' : '#000';
},
align() {
return someCondition ? 'left' : 'right';
}
}
}
</script>
A unique ID (or some other data-attribute) is required to "scope" the styles to just this component.
This is a nice solution as you can use v-for loops to generate the style content if required (which can be reactive to changes in your components data/props/computed props)
<component is="style" type="text/css">
<template v-for="item in items">
[data-id="{{ uniqueId }}"] div.bar[data-div-id="item.id"]::before {
content: "{{ item.content }}";
color: {{ item.color }};
}
</template>
</component>
I just created a computed property and used it in the template as v-html
<div v-html="css"></div>
computed: {
css () {
return `<style>${this.item.css}</style>`
}
}
<template>
<header>
<hamburger></hamburger>
<app-title></app-title>
<lives></lives>
</header>
</template>
<script>
export default {
name: 'Titlebar',
data() {
return {
}
}
}
</script>
<style lang="scss" scoped>
#import "../styles/variables";
header {
padding: $padding-titlebar;
position: relative;
}
lives {
position: absolute;
right: 2.5vh;
}
</style>
Is it possible to use component tags like any regular HTML tag for styling purposes like I've written down there in lives { }?
I see that that writing <lives class="lives"> and using .lives { } in css works but that seems kinda redundant, would rather like to ommit adding aditional classes if it's possible to just use component tag.
I understand that Vue compiles <lives> into HTML code and that there is no "lives" tag for css to use after it's compiled, but still wondering.
Vue component's name has no relationship with css rule, but it's template does.
Vue component has a template property, it contains html tag. and also, you can use custom html tag in template. for example:
template: `<lives class="lives">{{a}}</lives>`
so now you can define css rule by lives tag.
You can use vue-custom-element:
https://github.com/karol-f/vue-custom-element
First register your component with:
Vue.customElement('widget-vue', {
props: [
'prop1',
'prop2',
'prop3'
],
data: {
message: 'Hello Vue!'
},
template: '<p>{{ message }}, {{ prop1 }}, {{prop2}}, {{prop3}}</p>'
});
Then you can do:
widget-vue {
display: block;
background: red;
...
}
If you want to register a Single File Component, register your own like this:
import TopBar from '#/components/core/TopBar'
Vue.customElement('top-bar', TopBar)
I hope it helps, Cheers!