Laravel 8 pass data from blade to Vue 3 - javascript

I try to pass data from Laravel blade to Vue with props and I get undefined in console.
I tried also
<example-component :course="{{ $course }}"></example-component>
<example-component course="{{!! $course !!}}"></example-component>
index.blade.php
#extends('layouts.app')
#section('content')
<div id="app">
</div>
<example-component course="{{ $course }}"></example-component>
<script src="{{asset('js/course/app.js')}}"></script>
#endsection
app.js
import { createApp } from 'vue';
import App from './components/App.vue'
import router from '../../router'
createApp(App).use(router).mount("#app")
App.vue
<template>
{{ course }}
</template>
<script>
export default {
props: ['course'],
mounted() {
console.log(this.course)
}
}
</script>

The best practice is to make you component call an API to get the course.
If it's not worth an API try to pass the $course as attr to your #app element. Then you can get your course with getAttribute
<div id="app" course="{{json_encode($course)}}"></div>
in vue.js:
document.getElementById('app').getAttribute('course')

Related

How to use #heroicons/vue in Nuxt3?

i want to import #heroicons/vue in Nuxt 3 but my icon not appear in frontend.
my setup:
import { HomeIcon, FilmIcon, PlusIcon } from "#heroicons/vue/solid"
my html:
<template v-for="(profileItem, i) in accountSetFields" :key="i">
<ProfileItems :user="user" :item="profileItem" />
<template v-slot:icon>
<component :is="profileItem.icon"></component>
</template>
</ProfileItems>
</template>
the variable profile.Item.icon has a string value of "HomeIcon"
I have tried to pass the value directly to the child component "ProfileItem.vue" but i receive the same error message.
When i pass the value directly as string ("HomeIcon" instead of profile.Item.icon) than it works because it mentioned the attribute from import { HomeIcon, FilmIcon, PlusIcon } from "#heroicons/vue/solid
<component :is="HomeIcon"></component>
Did anyone know how to load the icons dynamically?
That one works well
<script setup>
import { HomeIcon, FilmIcon, PlusIcon } from "#heroicons/vue/24/solid"
const icons = reactive({
home: HomeIcon,
film: FilmIcon,
plus: PlusIcon,
})
</script>
<template>
<component :is="icons.home"></component>
</template>
as explained here, you need the 24 in your import (for the size).
Not sure but this may also help maybe, didn't have to use that myself: https://github.com/tailwindlabs/heroicons/issues/564
Or you can forget about worrying about various icons configuration and fallback to that one (configured once and for all): https://stackoverflow.com/a/72055404/8816585
You can also use it without <component/> and register the icon as a component. Should also work with the composition api.
<template>
<CheckCircleIcon />
</template>
<script>
import { CheckCircleIcon } from "#heroicons/vue/24/solid";
export default {
components: {
CheckCircleIcon,
}
}
</script>

How to call Vue 3 method from outside the app

what I want is to call a method, declared in vue 3 app form outside the component of the page. So what I did sofar:
App.vue
<script setup>
function test(){
console.log('test');
}
</script>
vue.js
import { createApp } from 'vue'
import App from 'App.vue'
window.app = createApp(App).mount('#app')
index.html
<div id="app"></app>
<script src="app.js"></script>
<script>
fuction callTest(){
window.app.test() // <-- this returns undefined
}
</script>
however it worked with vue2. Any idea how to get it work with vue3?
You need to use defineExpose inside in the first file in order to use it outside the component:
<script setup>
function test(){
console.log('test');
}
defineExpose({
test
})
</script>

How to target elements inside <script setup> of Vue 3 component?

How can I target the element with test class inside this vue component:
<template>
<div id="test" class="test">
</div>
</template>
<script setup>
console.log(document.querySelector('.test'))
</script>
This component is imported into another component. The console outputs null.
the component is not rendered before that script is run
You want to wait until it is mounted
<template>
<div id="test" class="test">
</div>
</template>
<script setup>
import { onMounted } from 'vue';
onMounted(() => {
console.log(document.querySelector('.test'))
});
</script>
In general, there's hardly ever any need to use DOM methods like that in vue though - I won't say never, because I know as soon as I say that, someone will come up with a valid reason to
I never have though
The best practice is to use ref instead of DOM manipulations methods, and also use onMounted hook to check the element as mentioned in the following example:
<script setup>
import { ref,onMounted } from 'vue'
const input =ref()
onMounted(()=>{
input.value.focus()
})
</script>
<template>
<input ref="input">
</template>
you can use onMounted for target the element inside vue component:
<script setup>
import { onMounted } from 'vue'
onMounted(() => {
console.log(document.querySelector('.test'));
})
</script>
but I recommend use ref instead of DOM manipulations method:
<script setup>
import { ref, onMounted } from 'vue'
const el = ref()
onMounted(() => {
el.value // <div>
})
</script>
<template>
<div ref="el"></div>
</template>
docs: https://vuejs.org/api/composition-api-lifecycle.html#onmounted

Passing HTML or Components to the Vue Plugin

I have created the basic Vue component which is as follow.
<template>
<div class="example">
/* here render the component or HTML passed by pluing */
</div>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
name: 'Example',
});
</script>
Now I need to create a plugin that will render any HTML or Component passed to the Example.I know the basic syntax of plugins and how to use them in the Vue but don't know how to do this task since I am a newbie to Vue.
export default {
install(vue, opts){
/* how to take the component or HTML and pass to `Example` Component */
}
}
I need to implement these in vue2.
You can use a slot to render an arbitrary HTML inside any of your components.
Your Example Component:
<template>
<div class="example">
<slot />
</div>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
name: 'Example',
});
</script>
Then use it like this:
<template>
<example>
<div>Render me inside the slot</div>
</example>
</template>
And it will result in the following rendered HTML:
<div class="example">
<div>Render me inside the slot</div>
</div>
Then in you plugin you can use your Example component and pass any html you want to it
Update: this how your plugin might look like. Just create a global component inside of it
import Vue from 'vue'
const ExamplePlugin = {
install(Vue){
Vue.component('Example', {
name: 'Example',
template: '<div class="example"><slot /></div>'
})
}
}
Then you can Vue.use(ExamplePlugin) and Example component will be available globally in your application

How to insert external javascript into a Vue component

I am trying to insert a custom JavaScript (a sketcher) into a Vue component but no luck so far. When I try inserting javascript directly into a template like this:
<template>
<div id="sketcher">
var sketcher = new ChemDoodle.SketcherCanvas('sketcher', 400, 300);
</div>
</template>
I get an error: "Templates should only be responsible for mapping the state to the UI. Avoid placing tags with side-effects in your templates, such as , as they will not be parsed."
My another attempt is to create a component in a different .js file and import it into a Vue component.
sketcher.js:
export default ({
mounted(){
return new ChemDoodle.SketcherCanvas('sketcher', 400, 300)
}
})
Home.vue
<template>
<div id="sketcher">
<app-sketcher></app-sketcher>
</div>
</template>
<script>
import sketcher from './sketcher';
export default {
components: {
"app-sketcher": sketcher
}
}
</script>
but I get this error: "Failed to mount component: template or render function not defined". I would highly appreciate any suggestions on how to fix this or to propose other options of embedding javascript into a Vue component.
Your first error message is self-explanatory: you cannot put a <script> tag in the <template> of a single-file Vue component.
In your second example, you aren't defining a template for the app-sketcher component when you register it in your Home.vue file. Your sketcher.js file exports just the definition for a mounted hook and nothing else.
You can make a Sketcher.vue file:
<template>
<div id="sketcher"></div>
</template>
<script>
export default {
mounted() {
return new ChemDoodle.SketcherCanvas('sketcher', 400, 300)
}
}
</script>
And then use import it and use it in your Home.vue file like so:
<template>
<app-sketcher/>
</template>
<script>
import AppSketcher from './Sketcher';
export default {
components: { AppSketcher }
}
</script>

Categories