Managing alpine component outside x-data - alpine.js

So I am trying to manage the data of an alpine component outside the x-data... for example:
<div x-data="toastr()" x-show="isOpen">
<span x-text="title"></span>
<span x-text="body"></span>
</div>
<script>
function toastr() {
isOpen: false,
title: '',
body: '',
open() {
this.isOpen = true
},
set(data) {
this.title = data.title
this.body = data.body
}
}
</script>
.... other html
<script>
toastr().open();
toastr().set({
'title': "Hello",
'body': "Some body",
});
</script>
When I call toastr() for open and set, it doesn't show the toaster and I am assuming it doesn't update the title and body too... How can I achieve this?

Related

Trying to get a single data and display in a vue component, but nothing is displaying

I am using Laravel 5.8 + Vue.js in my project.
Trying to get a single data from a controller but nothing is displaying.
I added the 12345 in the component to check if the component is working, 12345 is showing well.
controller
public function getSingleData($idx)
{
$paymentData = PaymentData::where('idx', $idx)->first();
return view('paydetail')->with('paymentData', $paymentData);
}
router
Route::view('/paylist', 'paylist')->name('paylist.view');
Route::get('/paylist/data', 'PaymentController#getPaymentData')->name('paylist');
Route::get('/paydetail/{idx}', 'PaymentController#getSingleData')->name('paydetail');
blade
#extends('layouts.default')
#section('content')
<div class="container">
<paydetail :idx="{{ $paymentData->idx }}"></paydetail>
app.js
Vue.component('paydetail', require('./components/Paydetail.vue').default);
Paydetail.vue
<template>
<div>
<h2>12345</h2>
<div v-for="val in paymentData">
<h2>{{ val.app_name }} </h2>
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
props: [ 'idx' ],
data() {
return {
paymentData: [{}],
}
},
created() {
this.paymentData = this.getPayDetailData();
console.log(this.idx);
console.log("here");
},
methods: {
getPayDetailData() {
axios({
method: 'GET',
url: '/paydetail/'+ this.idx
}).then(
response => {
console.log(response)
return response
},
error => {
console.log(error)
}
)
},
},
}
</script>
The result of console.log(response) is weird. It shows the whole html document which I don't understand at all.
It shows like this.
{data: "<!DOCTYPE html>↵<html>↵ <head>↵ <meta ch…>↵<!-- For Datatable -->↵↵↵ </body>↵</html>↵", status: 200, statusText: "OK", headers: {…}, config: {…}, …}
What did I wrong here?

Vue.js component conflict in laravel blade view

I have 2 of the same components in my laravel blade view, but they are conflicting.
What i'm trying to accomplish:
I've made a vue component that uploads a file to firebase and stores it in my database. In my blade view i have 2 places where i want to use this component. I configure the component with props so the component knows where to store the file.
What going wrong:
Every time i try to upload a file with the second component, i fire the function in the first component. How do i fix that the components can't conflict?
My laravel balde view:
component 1
<uploadfile
:key="comp100"
:user_data="{{ Auth::user()->toJson() }}"
store_path="/users/{{ Auth::user()->username }}/settings/email_backgrounds"
:store_route="'settings.project_email'"
:size="1000"
fillmode="cover"
></uploadfile>
component 2
<uploadfile
:key="comp200"
:user_data="{{ Auth::user()->toJson() }}"
store_path="/users/{{ Auth::user()->username }}/settings/email_backgrounds"
:store_route="'settings.project_email'"
:size="1000"
fillmode="cover"
></uploadfile>
The Vue component:
<template>
<div class="vue-wrapper">
<FlashMessage position="right top"></FlashMessage>
<div v-if="loading" class="lds-dual-ring"></div>
<div class="field">
<div class="control">
<label class="button main-button action-button m-t-20" for="uploadFiles"><span style="background-image: url('/images/icons/upload.svg')"></span>Kies bestand</label>
<input type="file" name="uploadFiles" id="uploadFiles" class="dropinput" #change="selectFile">
</div>
</div>
</div>
</template>
<script>
import { fb } from '../../firebase.js';
export default {
data() {
return {
fileObject: {
filePath: null,
url: null,
file: null,
resizedPath: null
},
loading: false
};
},
mounted() {
console.log(this.size)
console.log(this.fillmode)
},
props: [
'user_data',
'store_path',
'store_route',
'size',
'fillmode'
],
methods: {
selectFile(event)
{
var file = event.target.files[0];
this.fileObject.file = file
this.fileObject.filePath = this.store_path + '/' + file.name
this.fileObject.resizedPath = this.store_path + '/resized-' + file.name
if(file.type == 'image/png' || file.type == 'image/jpeg')
{
this.uploadFile(this.fileObject)
} else {
this.flashMessage.success({
title: 'Oeps!',
message: 'De afbeelding moet een png of een jpeg zijn!',
blockClass: 'success-message'
});
}
},
uploadFile(fileObject)
{
var vm = this
console.log(fileObject)
var storageRef = fb.storage().ref(fileObject.filePath)
var uploadTask = storageRef.put(fileObject.file)
this.loading = true
uploadTask.on('state_changed', function(snapshot){
var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
},function(error) {
}, function() {
var resizeImage = fb.functions().httpsCallable('resizeImage')
resizeImage({filePath: fileObject.filePath, contentType: fileObject.file.type, watermark: false, size: vm.size, fit: vm.fillmode}).then(function(result){
var downloadRef = fb.storage().ref(fileObject.resizedPath);
downloadRef.getDownloadURL().then(function(url){
fileObject.url = url
vm.loading = false
vm.storeImage(fileObject)
}).catch(function(error){
console.log(error)
})
}).catch(function(error){
});
});
},
storeImage(file)
{
axios.post('/api/app/store_file', {
api_token: this.user_data.api_token,
user: this.user_data,
file: file,
storeRoute: this.store_route
}).then((res) => {
location.reload()
}).catch((e) => {
});
}
}
}
</script>
Does someone know how to fix this?

Update Global Component data

I am updating this with my new code. I need to get a reference to the "allImages" property of the data object within the dropzones "onSuccess" method. Is there any way to do it.
<template>
<div class="container">
<div class="row">
<form action="/user/album_images" id="dropzone" class="dropzone" method="post">
<input type="hidden" id="album_id" name="album_id" :value=image.id>
</form>
</div>
<div class="row">
<div class="col-md-3" v-for="image in albumImages">
<img src="https://mysite.nyc3.digitaloceanspaces.com/users/62MY43og3ZNCLU4y53iwoqdEfUZUWFEfDM2f9krn.png" class="img-responsive" style="width: 120px; height: 90px;">
</div>
</div>
</div>
</template>
<script>
export default {
props: ['theImage','theAlbumImages'],
data() {
return {
image: this.theImage,
albumImages: this.theAlbumImages
}
},
methods: {
},
}
let csrfToken = document.querySelectorAll('meta[name=csrf-token]')[0].getAttributeNode('content').value
Dropzone.options.dropzone = {
paramName: "file", // The name that will be used to transfer the file
maxFilesize: 10, // MB
acceptedFiles: "image/*",
addRemoveLinks: true,
init: function() {
this.on("success", function(file,albumImage) {
// I want to get a reference to the vue instances "albumImages" property
});
},
headers: {
'x-csrf-token': csrfToken
}
};
</script>
You can try to use vue-script2
You will be able to access vue variables like in template.
<script2>
....
this.on("success", function(file,albumImage) {
var x = {{albumImages}}
});
....
</script2>
Although it might not work. Other option would be to try load function in mounted. E.g.
import VS2 from 'vue-script2'
export default {
name: 'freshchat',
mounted() {
VS2.load('yourdropzonejs script').then(() => {
var vm = this
.....
this.on("success", function(file,albumImage) {
vm.albumImages
});
})
}
}

Laravel router-link works only the first time

I am trying to fetch results from database in News.vue, and display them in Topnews.vue. I have two links fetched. When I click link1, it shows up the Topnews.vue template with everything working as intended, however, if i click link2, nothing happens, except for that the URL changes, but the template does not show up the result. If i refresh the page and click link2 or click on the navbar, then link2, it shows up, and same, clicking then link1, changes the URL, but doesnt show up. I'm really stuck on that and I'd be really glad if you help me out on that issue. Hope you understand.
News.vue
<template id="news">
<div class="col-sm-5">
<div class="cars" v-for="row in filteredNews" >
<div class="name" >
<p class="desc_top_time">{{row.created_at}}</p>
<span class="last_p"> {{row.category}}</span>
<h3 style="margin-bottom:-4px; font-size: 16px;">
<router-link class="btn btn-primary" v-bind:to="{name: 'Topnews', params: {id: row.id} }">{{row.title}}</router-link></h3>
</div></div></div>
</template>
<script>
export default {
data: function() {
return {
news: [],
}
},
created: function() {
let uri = '/news';
Axios.get(uri).then((response) => {
this.news = response.data;
});
},
computed: {
filteredNews: function() {
if (this.news.length) {
return this.news;
}
}
}
}
</script>
Topnews.vue
<template id="topnews1">
<div class="col-sm-7">
<div class="cars">
<img :src="topnews.thumb" class="img-responsive" width=100%/>
<div class="name" ><h3>{{ topnews.title }}</h3>
<p>
<br>{{ topnews.info }}<br/>
</p>
</div></div></div>
</template>
<script>
export default {
data:function(){
return {topnews: {title: '', thumb: '', info: ''}}
},
created:function() {
let uri = '/news/'+this.$route.params.id;
Axios.get(uri).then((response) => {
this.topnews = response.data;
});
}
}
</script>
Like GoogleMac said Vue will reuse the same component whenever possible. Since the route for both IDs use the same component Vue will not recreate it, so the created() method is only being called on the first page. You'll need to use the routers beforeRouteUpdate to capture the route change and update the data.
in TopNews.vue:
export default {
data:function(){
return {topnews: {title: '', thumb: '', info: ''}}
},
beforeRouteEnter:function(to, from, next) {
let uri = '/news/'+ to.params.id;
Axios.get(uri).then((response) => {
next(vm => {
vm.setData(response.data)
})
});
},
beforeRouteUpdate: function(to, from, next) {
let uri = '/news/'+ to.params.id;
Axios.get(uri).then((response) => {
this.setData(response.data);
next();
});
},
methods: {
setData(data) {
this.topnews = data
}
}
}
If you click a link referring to the page you are on, nothing will change. Vue Router is smart enough to not make any changes.
My guess is that the IDs are messed up. If you are using Vue devtools you will be able to easily see what data is in each link. Are they as you expect.

Vue Object is Empty

I'm using Vuejs to display data from an API to a template. I'm trying to figure out why I am not returning data for the team so I can display in for the template. Right now when I use the VueJS Chrome Extention it shows that the team is an empty object.
<div v-if="team">
<div class="row">
<div class="col-12 col-sm-12">
<div class="fw-700 pb3 mb5" style="border-bottom: 1px solid #333;">Name:</div>
<div class="mb10" style="font-size: 20px;">{{ team.name }}</div>
</div>
</div>
<script>
module.exports = {
http: {
headers: {
'X-CSRF-TOKEN': window.Laravel.csrfToken
}
},
props: [ 'id', 'editable' ],
data: function(){
return {
modalName: 'additionalInfo',
team:{
}
}
};
},
methods: {
fetchInfo: function(){
this.$http.get('/api/teams/info', { params: { id: this.id } }).then((response) => {
this.team = response.data;
});
},
},
}
}
</script>
It is empty because your method fetchInfo isn't being called, so you need to do something like this:
created () {
this.fetchInfo()
}
This will call the function fetchInfo which in turn will fetch and fill this.team

Resources