Can I inject custom view components into a Vue.js grid component? - components

I have a data grid component in Vue.js, which looks a bit like the one in the official sample: http://vuejs.org/examples/grid-component.html
Based on the input data instead of pure strings sometimes I'd like to display entries "decorated" as a checkbox or a v-link component (not exclusively, I may need to render other components too, like unescaped HTML or an img).
Obviously I don't want to prepare the Grid component for all the use cases, so this is not what I'd like to do:
A sample data model to be displayed:
model = [
{
field1: 'some string',
field2: 'another string',
field3: { // this should be a checkbox
state: true
},
field4: { // this should be an <a v-link>
url: 'http://whatever',
label: 'go somewhere'
}
}
]
A relevant excerpt from the Grid component:
<template>
...
<tr v-for="entry in model">
<td>
<div v-if="typeof entry === 'object' && entry.hasOwnPropery('url')">
<a v-link="entry.url">{{ entry.label }}</a>
</div>
<div v-if="typeof entry === 'object' && entry.hasOwnProperty('state')">
<input type="checkbox" v-model="entry.state">
</div>
<div v-else>
{{ entry }}
</div>
</td>
</tr>
...
</template>
What's the Vue.js philosophy for injecting custom components as decorators? I want my Grid to be completely agnostic regarding these decorator components.

This would be a good place for a mutable component piece. You define a few different decorator components and then use your data to decide which one should be used for rendering.
Template:
<div id="app">
<ul>
<li
v-for="entry in entries"
>
<component :is="entry.type">
{{ entry.content }}
</component>
</li>
</ul>
</div>
Component:
new Vue({
el: '#app',
components: {
'blank': {
template: '<div><slot></slot></div>'
},
'green': {
template: '<div style="color: #0f0;"><slot></slot></div>'
},
'red': {
template: '<div style="background-color: #f00;"><slot></slot></div>'
}
},
computed: {
entries: function() {
return this.raw_entries.map(
function(entry) {
if (typeof entry !== "object") {
return { type: 'blank', content: entry }
}
if (!entry.hasOwnProperty('type')) {
entry.type = 'blank'
}
return entry
}
)
}
},
data: {
raw_entries: [
'Base Text',
{
type: 'green',
content: 'Green Text'
},
{
type: 'red',
content: 'Red Background'
}
]
}
})
JsFiddle Working example using lists

Related

trigger vue-typed-js animation when element is in view

I'm using vue-typed-js library to trigger typing animation with nuxt.js.It works perfectly on load, but I want to trigger this animation when user scrolls to that particular section. Basically controlling typing animation so they work only when element is in view. See this example in wordpress https://www.ennostudio.com,
here is my code for second section of the website.
added v-observe-visibility which works as well for adding classes for elements in view. am also using i18n for string translations.
<template>
<section>
<b-container class="enno_clients section">
<b-row>
<b-col cols="6">
<h6>02 / {{ $t('home.clients.subheading') }}</h6>
<vue-typed-js
v-observe-visibility="{ callback: isViewableNow, once: true }"
:class="{ 'visible': showAnimation, 'invisible': !showAnimation }"
:typeSpeed="30" :showCursor="false" :strings="[ $t('home.clients.heading') ]" >
<h2 class="main_hero_heading typing"></h2>
</vue-typed-js>
</b-col>
<b-col cols="6" >
asd
</b-col>
</b-row>
</b-container>
</section>
</template>
<style scoped>
.visible { visibility: visible; opacity:1; }
.invisible { visibility: hidden; opacity:0; }
</style>
<script>
export default {
name: 'Clients',
data() {
return {
show_hero_content: true,
showAnimation: false,
VueTypedJs: ''
}
},
methods:{
isViewableNow(isVisible, entry) {
this.showAnimation = isVisible;
console.log('isViewableNow');
}
},
mounted() {
this.show_hero_content = false;
},
}
</script>

Is there a way to reference the images in vue?

I'm building a SPA using vue.js, I need to assign a div background-image referencing something in the following path:
I'm trying to reference src/assets/img/firstCard.jpg but for some reason it doesn't shows the image, this is how I'm binding the image:
HTML:
<a class="card">
<div
class="card__background"
v-bind:style="secondCard">
</div>
<div class="card__content">
<p class="card__category">Gratuita</p>
<h3 class="card__heading">Ademas en diferentes plataformas.</h3>
</div>
</a>
JS:
<script>
export default {
data () {
return {
thirdCard: {
'background-image': require('#/assets/img/firstCard.jpg')
},
secondCard: {
'background-image': require('#/assets/img/firstCard.jpg')
},
firstard: {
'background-image': require('#/assets/img/firstCard.jpg')
}
}
}
}
</script>
Thank you all for your time.
You can try to make method or computed property:
getUrl (img) {
return require(`#/assets/img/${img}.jpg`);
}
then call that method in data object (for background-image you need to specify url):
data () {
return {
firstCard: {
'background-image': `url(${this.getUrl('firstCard')})`
}
}
},

How to send data from parent to child component in Vue.js

I am new to vue.js and currently I am building an app for learning purposes.
What I want to do:
I have a parent component which has a bunch of buttons with different id's.
The child component will wait for those id's to be sent by the parent and it will decide what to display based on the id. Thats all.
I wont post the full code because it's too large but I have tried a bunch of stuff like props and state but honestly it is so confusing.
I come from React background and I am still confused.
Parent component
<template>
<button id="btn1">Show banana</button>
<button id="btn2">Show orange</button>
</template>
<script>
export default {
name: 'Parent',
data: function {
//something
},
props: {
// ?????
}
};
</script>
**Child component**
<template>
<p v-html="something.text">
</template>
<script>
export default {
name: 'Child',
data: function() {
something: ''
if(id from parent === id I want) {
something = object.withpropIneed
}
},
};
</script>
You need to map the data from parent and pass it to child, thats it!
In example i make passing a html string and binding that html received through 'fromParentHtml' prop mapped on child, so inside child component 'this.fromParentHtml' pass to exists because it is defined in props and every time you click in parent button executes the 'show' function and change the value from passed prop to child through parent 'html' data .. =)
<template>
<div>
Current html sent to child '{{html}}'
<br>
<button #click="show('banana')">Banana</button>
<button #click="show('orange')">Orange</button>
<button #click="show('apple')">Apple</button>
<!-- Create child component -->
<child-component :fromParentHtml="html"></child-component>
</div>
</template>
<script>
export default {
name: "test3",
components: {
'child-component': {
template: "<div>Child component... <br> <span v-html='fromParentHtml'></span> </div>",
//Child component map a prop to receive the sent html from parent through the attribute :fromParentHtml ...
props: {
fromParentHtml: {
required: true,
type: String
}
}
}
},
data(){
return {
html: ''
}
},
methods: {
show(fruit){
this.html = '<span>The fruit is ' + fruit + ' !</span>';
}
}
}
</script>
<style scoped>
</style>
If helped you please mark as correct answer! Hope it helps.
Edit 1:
Assuming you have webpack to work with single file components, to import another component just do:
<template>
<div>
<my-child-component></my-child-component>
</div>
</template>
<script>
//Import some component from a .vue file
import ChildComponent from "./ChildComponent.vue";
export default {
components: {
//And pass it to your component components data, identified by 'my-child-component' in the template tag, just it.
'my-child-component': ChildComponent
},
data(){
},
methods: {
}
}
</script>
Just for the sake of it, I think you were looking for this:
<template>
<button id="btn1" #click = "id = 1">Show banana</button>
<button id="btn2" #click = "id = 2">Show orange</button>
<child-component :childid = "id"></child-component>
</template>
<script>
import childComponent from 'childComponent'
export default {
name: 'Parent',
data () {
return {
id: 0
}
},
components: {
childComponent
}
};
</script>
**Child component**
<template>
<p v-html="something.text">
</template>
<script>
export default {
name: 'Child',
props: {
childid: String
},
data: function() {
something: ''
if(this.childid === whatever) {
something = object.withpropIneed
}
},
};
</script>
Solved my problem by taking a different approach.
I have implemented state and my component behaves exactly as I wanted to.
I found this link to be helpful for me and solved my problem.
Thank you.

Vue js 2 Method not working from click event

I have a vue component which prints out a list of radio buttons. I have a watch on internalValue which sends the selected value to the root
I am trying to send a console.log on a click event using a method called doSomething but it is not working. Furthermore I am not getting any errors or warnings.
Load Component
Vue.component('topic', require('./components/Topicselect.vue'));
Use Component
<div class="form-group" id="topic">
<topic v-model="selectedTopic"></topic>
</div>
Initialise Vue
new Vue({
el: '#topic',
data: {
selectedTopic: null
}
});
Component
<template>
<div>
<label v-for="topic in topics" class="radio-inline radio-thumbnail" style="background-image: url('http://s3.hubsrv.com/trendsideas.com/profiles/74046767539/photo/3941785781469144249_690x460.jpg')">
<input type="radio" v-model="internalValue" :click="doSomething" name="topics_radio" :id="topic.id" :value="topic.name">
<span class="white-color lg-text font-regular text-center text-capitalize">{{ topic.name }}</span>
</label>
</div>
</template>
<script>
export default {
props: ['value'],
data () {
return {
internalValue: this.value,
topics: []
}
},
mounted(){
axios.get('/vuetopics').then(response => this.topics = response.data);
},
watch: {
internalValue(v){
this.$emit('input', v);
console.log('the value is ' + this.value);
}
},
methods: {
doSomething: function (){
console.log('doSomething is firing');
}
}
}
</script>

Kendo UI Core Listview Edit Template with Autocomplete TextBox(Kendo Autocomplete)

How to use the Kendo UI Autocomplete textbox inside the Listview Edit Template??While trying to apply the autocomplete option the text box not taking it.The requirement also includes a server side filtering option.This needs to be implemented in an ASP.NET MVC5 Web Application.
I am working on Kendo UI for Jquery and I have implemented something similar. Idea behind the implementation is that you have to add the autocomplete when you are editing the ListView.
I am sharing the "Edit Template" and "ListView JS" below.
I found the idea here http://jsfiddle.net/F4NvL/
<script type="text/x-kendo-tmpl" id="editTemplate">
<div class="product-view k-widget">
<dl>
<dt>Product Name</dt>
<dd>
<label for="PAPC">Project Code<span class="k-icon k-i-star requiredstar" data-toggle="tooltip" title="Required"></span></label>
<input type="text" required name="PAPC" validationMessage="Hotel is required" data-bind="value: ProjectCode" />
<span class="k-invalid-msg" data-for="PAPC"></span>
</dd>
</dl>
<div class="edit-buttons">
<a class="k-button k-update-button" href="\\#"><span class="k-icon k-i-check"></span></a>
<a class="k-button k-cancel-button" href="\\#"><span class="k-icon k-i-cancel"></span></a>
</div>
</div>
var listView = $("#lvPA").kendoListView({
dataSource: datasrc,
template: kendo.template($("#template").html()),
editTemplate: kendo.template($("#editTemplate").html()),
edit: function (e) {
var model = e.model;
var item = $(e.item[0]);
var projectcode = item.find('[name="PAPC"]'); //Get your element
//Add a autocomplete here
projectcode.kendoAutoComplete({
valueTemplate: '<span>#:data.ProjectCode#</span>',
template: projectTemplate,
minLength: 3,
autoWidth: true,
dataTextField: "ProjectCode",
dataSource: new kendo.data.DataSource({
type: "GET",
serverFiltering: true,
transport: {
read: ProjectAPI,
parameterMap: function (data, type) {
return { filter: $('[name="PAPC"]').val() };
}
},
}),
height: 200
});
}
}).data("kendoListView");

Resources