vuejs 2 how to add child component without npm - vuejs2

I use vuejs2 and want to attach some component to my main one. Now I can have something like this:
var Component ={
template: '<div>1</div>'
};
However, I want the thing in template to be a partial html from some other directory, like template:'../../com/a.html', I heard x-template but not know how to use it. Also, is there some lib other than webpack/browserify/npm series I can use directly just by add the script in the end of html?

You have your template file as
/* yourPath/name.template.html */
<div class="myClass">
1
</div>
Then in the component file, you can do following:
export default {
template: require('yourRelativePath/name.template.html'),
data: function () {
return {
};
}
}

Related

Unable to add elements using the setAttribute

I am using the VUE JS code and trying to add the setAttribute to some of the tags.
Here is the code I am using :
changetab() {
const demoClasses = document.querySelectorAll(".delCon__select");
demoClasses.forEach(button => {
button.setAttribute("tabindex", "0");
});
return true;
},
but when I view in the code inspector, It does not show added to it, I have added the above function in computed.
template is like this :
<template>
<el-container class="orders"></el-download>
</template>
You need to make this type of request in Vue's Lifecycles, like: created or mounted.
Something like:
mounted() {
this.changetab()
}
Computed would not be the most appropriate place for this type of action.

Find nearest parent Vue component of template ref (Vue 3)

When a Vue template ref is mounted, I want to get the nearest parent Vue component. This should be generic and work for any template ref so I've put it in a composition function (but that's just an implementation detail).
I had this working but my implementation used elem.__vueParentComponent while iteratively searching an element's ancestors. While reading the Vue source code I saw __vueParentComponent was only enabled for dev mode or if dev tools is enabled in production. Thus, I don't want to rely on that flag being enabled.
I thought this might be possible using vnodes but this isn't easily google-able. Here's an example of what I'm trying to do:
function useNearestParentInstance(templateRef) {
function getNearestParentInstance(el) {
// code here
}
onMounted(() => {
const el = templateRef.value;
const instance = getNearestParentInstance(el);
// do something with instance
});
}
<template>
<div>
<SomeComponent>
<div>
<div ref="myElem"></div>
</div>
</SomeComponent>
</div>
</template>
<script>
export default {
setup() {
const myElem = ref();
// nearest would be SomeComponent's instance in this case
useNearestParentInstance(myElem);
...
}
}
</script>
If you want the nearest vue parent you can simply use
ref().$parent // Not sure if syntax is same in vue3
ref().$parent will get the first vuecomponent that is the parent of the ref that you placed.

Can I get Vue.js component as an instance?

I try to get the template of Vue.js component since I need it for another function.
First,
I have a function that needs a Vue.js component template because I want the data in the template to dynamically change and not just some static HTML.
Secondly,
I have a problem to get a template from Vue.js component. Maybe they are not allowed to do that but I am not sure. I am new to Vue.js.
But from my understanding of JS, maybe this can happen.
I am tried to do something like this:
let vmComponent = Vue.component('VueComponent', {
data() {
return {
title: 'I am a Vue.js component manually.'
}
},
template: `
<div>
<h2>Template Exchange</h2>
<h3>{{ title }}</h3>
</div>`,
});
console.log(vmComponent.template);
I hope to get the HTML string when I run vmComponent.template
If this way of doing things is not possible. Is there any other ways I can get Vue.js component template as HTML String.
For example, maybe in a new.Vue({})
It's possible to access component template with vmComponent.options.template.
A template can be declared as a string for reuse:
export const template = `...`;
const vmComponent = Vue.component('VueComponent', {
template,
...
});
This may not work with pre-compiled templates.

Access the component name from a Vue directive

I want to create a custom Vue directive that lets me select components on my page which I want to hydrate. In other words, this is what I want to archive
I render my Vue app on the server (ssr)
I attach a directive to some components, like this:
<template>
<div v-hydrate #click="do-something"> I will be hydrated</div>
</template>
I send my code to the client and only those components that have the v-hydrate property will be hydrated (as root elements) on the client.
I want to achieve this roughly this way:
I will create a directives that marks and remembers components:
import Vue from "vue";
Vue.directive("hydrate", {
inserted: function(el, binding, vnode) {
el.setAttribute("data-hydration-component", vnode.component.name);
}
});
My idea is that in my inserted method write a data-attribute to the server-rendered element that I can read out in the client and then hydrate my component with.
Now I have 2 questions:
Is that a feasible approach
How do I get the component name in el.setAttribute? vnode.component.name is just dummy code and does not exist this way.
PS: If you want to know why I only want to hydrate parts of my website: It's ads. They mess with the DOM which breaks Vue.
I could figure it out:
import Vue from "vue";
Vue.directive("hydrate", {
inserted: function(el, binding, vnode) {
console.log(vnode.context.$options.name); // the component's name
}
});
I couldn't get the name of my single file components using the previously posted solution, so I had a look at the source code of vue devtools that always manages to find the name. Here's how they do it:
export function getComponentName (options) {
const name = options.name || options._componentTag
if (name) {
return name
}
const file = options.__file // injected by vue-loader
if (file) {
return classify(basename(file, '.vue'))
}
}
where options === $vm.$options

vuejs handsontable official and calling handsontable method

I'm a beginner, this is probably more of a javascript problem than vue but anyway:
there a plugin for spreadsheet named handsontable and in the normal use you make the table by doing this
hot = new Handsontable(container, {option})
and then you can use the method like hot.loadData() etc..
To use handsontable with vuejs, there a wrapper we can find here https://github.com/handsontable/vue-handsontable-official. With the wrapper you make a table like this :
<template>
<div id="hot-preview">
<HotTable :root="root" :settings="hotSettings"></HotTable>
</div>
</template>
<script>
import HotTable from 'vue-handsontable-official';
import Vue from 'vue';
export default {
data: function() {
return {
root: 'test-hot',
hotSettings: {
data: [['sample', 'data']],
colHeaders: true
}
};
},
components: {
HotTable
}
mounted () {
localforage.config({
driver: localforage.INDEXEDDB,
name: 'matchlist-database'
})
localforage.getItem('DB').then(function (value) {
console.log('then i fetch the DB: ' + JSON.stringify(value))
if (value !== 'null') {
console.log('dB contain something')
**root**.loadData(value)
}
</script>
So it work fine when i give an array but to load the data from a DB you must call the handsontable method hot.loadData(data).
i cannot find how to call this method in vuejs i always get the error
TypeError: root.loadData is not a function
i tried with all i could think of instead of root ex: HotTable.loadData(value)
but to no avail
Can someone point me out how i would call handsontable methods from the vuejs wrapper. Or point me out what kind of reading i should do to understand my mistake. Thank a lot
There are two problems here, not bad ones :)
1st problem:
If you want to refer to your data inside Vue's methods/computed properties/watchers/lifecycle events, you should use the this keyword. If you have data: function() { return { root: "root-value" }} and you would like to console.log that "root-value" string, you should write console.log(this.root) inside your mounted handler.
If you had something like:
data: function() {
return {
hot = new Handsontable(container, {option})
....
};
You could call hot.loadData() like so:
mounted() {
this.hot.loadData();
...
}
So this refers to the Vue instance which exposes your data properties.
2nd problem:
If I understand the component wrapper correctly, you are supposed to pass data to it as props, not call any Handsontable methods directly.
<HotTable :root="root" :settings="hotSettings"></HotTable>
This means that Vue passes whatever you have as root in your data to the HotTable component. It also passes whatever you have as settings in your data. In the example, HotTable receives these:
root: 'test-hot',
hotSettings: {
data: [['sample', 'data']],
colHeaders: true
}
Now if you want to change/update/modify/add data that should be passed to the HotTable component, you should update your data in the Vue instance. You should do something like this.hotSettings = something new and this.root = something else and the HotTable component would receive those.
To understand what's really happnening with the HotTable, read all of the component documentation. Really. You will save lots of time if you read through the documentation. It all makes sense after that!
https://v2.vuejs.org/v2/guide/components.html