Created() is not executing after delete. Inertia + Vuejs - laravel

I'm new with Vuejs and Inertia. I've created a simple dashboard using both and Laravel.
Everything works well except after delete an element, created() is not executing. Surely I'm making a mistake, but I don't found it.
Example:
Initial page:
If I press 'editar', I can edit the value.
I edit first value, 17 to 18.
And this works well. But if I want to delete the first element. The table is updated, because it depends from a prop (elements), but the elements below depend with created().
After removing:
Index.vue
<div class="mb-6 bg-white rounded-md shadow" v-if="elementsFiltrats[0].elements.length != 0">
<h2 class="pressupost_gastos_h2">General</h2>
<ul class="pressupost_gastos_ul">
<li v-for="e in elementsFiltrats[0].elements" :key="e.id" class="hover:bg-gray-100 focus-within:bg-gray-100 pressupost_gastos_li">
{{e.nom}} - {{e.valor.toFixed(2)}}€
</li>
</ul>
<h3 class="pressupost_gastos_h3">Total: {{elementsFiltrats[0].valor_total.toFixed(2)}}€ (+10%) = {{(elementsFiltrats[0].valor_total*1.10).toFixed(2)}}€</h3>
</div>
export default {
metaInfo: { title: 'Presupuestos' },
components: {
Icon,
Pagination,
SearchFilter,
},
layout: Layout,
props: {
filters: Object,
exercici: Object,
elements: Array,
comunitat: Object,
elementsagrupats: Array
},
data() {
return {
form: {
search: this.filters.search
},
elementsFiltrats: []
}
},
created(){
this.splitByType()
},
watch: {
form: {
deep: true,
handler: throttle(function() {
this.$inertia.get(this.route('pressuposts', this.exercici.id), pickBy(this.form), { preserveState: true })
}, 150),
},
'$route' : 'splitByType'
},
methods: {
reset() {
this.form = mapValues(this.form, () => null)
},
destroy(idExercici, idPressupost) {
if (confirm("Seguro que quieres eliminar el elemento del presupuesto?")) {
this.$inertia.delete(this.route('pressuposts.destroy', [idExercici, idPressupost]))
}
},
edit(idExercici, idPressupost) {
this.$inertia.get(this.route('pressuposts.edit', [idExercici, idPressupost]))
},
splitByType(){
console.log("hola")
// 0 general
// 1 escales
// 2 garatge
// valor_total
var elem = [
{
'elements' : [],
'valor_total': 0
},
{
'elements' : [],
'valor_total': 0
},
{
'elements' : [],
'valor_total': 0
}
];
this.elementsagrupats.forEach(element => {
var pos = 0;
if(element.casella === 'general'){
pos = 0;
}else if(element.casella === 'escales'){
pos = 1;
}else{
pos = 2;
}
elem[pos].elements.push({
'nom' : element['nom'],
'valor' : element['valor_total']
});
elem[pos].valor_total += element.valor_total;
});
this.elementsFiltrats = elem;
}
},
}
Controller:
Update method has:
Update code...
return Redirect::route('pressuposts', $exercici->id)->with('success', 'Element actualitzat.');
Destroy method has:
Delete code...
return Redirect::route('pressuposts', $exercici->id)->with('success', 'Element eliminat.');
Any help is appreciated.
Thanks.

Related

Property not defined error But it is defined Vue js Laravel

I have defined the function in my vue js file but it is giving me error for nameWithLang() function Please have a look
My Form
<multiselect v-model="selected" track-by="id" label="name" :options="options" :loading="isLoading" :internal-search="false" #search-change="getData" :multiple="true" :close-on-select="false" :hide-selected="true":internal-search="false" name="books[]" :show-labels="false" :custom-label="nameWithLang"></multiselect>
My vue js file
import AppForm from '../app-components/Form/AppForm';
Vue.component('coupon-form', {
mixins: [AppForm],
data: function() {
return {
form: {
name: '' ,
description: '' ,
valid_from: '' ,
valid_till: '' ,
discount: '' ,
enabled: false,
books: [],
},
isLoading: false,
options: [],
selected: [],
}
},
methods: {
nameWithLang({ name, sku }) {
return `${name} — ${sku}`
},
getData(query){
this.isLoading = true;
axios.post('/admin/books/find/'+query)
.then((response) => {
this.options = response.data;
this.isLoading = false;
})
.catch((error) => {
this.isLoading = false;
});
},
},
watch: {
selected (newValues) {
this.form.books = newValues.map(obj => obj.id)
}
}
});
Other properties and functions are working nameWithLang is not working
It gives me error this
Property or method "nameWithLang" is not defined on the instance but referenced during render.
why not you just return the value into a variable in data, and set the function into mounted/watch instead using the function to get the value.
just for refer, you can make the script like this :
import AppForm from '../app-components/Form/AppForm';
Vue.component('coupon-form', {
mixins: [AppForm],
data: function() {
return {
form: {
name: '' ,
description: '' ,
valid_from: '' ,
valid_till: '' ,
discount: '' ,
enabled: false,
books: [],
},
isLoading: false,
options: [],
selected: [],
newName: '',
}
},
methods: {
nameWithLang({ name, sku }) {
this.newName = `${name} — ${sku}`;
},
getData(query){
this.isLoading = true;
axios.post('/admin/books/find/'+query)
.then((response) => {
this.options = response.data;
this.isLoading = false;
})
.catch((error) => {
this.isLoading = false;
});
},
},
watch: {
selected (newValues) {
this.form.books = newValues.map(obj => obj.id)
this.nameWithLang();
}
}
});
then you can make the template like this:
<multiselect v-model="selected" track-by="id" label="name" :options="options" :loading="isLoading" :internal-search="false" #search-change="getData" :multiple="true" :close-on-select="false" :hide-selected="true":internal-search="false" name="books[]" :show-labels="false" :custom-label="newName"></multiselect>
this is just another way you can make it and the way i'm understand what actually you want to do. you want to pass the name with lang value into the :custom-label right? so why not just defined one more variable and add the value into the variable. so you just need to pass the value instead the function. in v-bind it's more appropiate to pass a property instead of a method

Select2 Add New Tag if no result returned in search

I have dropdown list where , after typing 2 or more symbols it starts to search in base nad returns values . if none is searched i want user to be able to add that tag as new one. here is my code so far
$("#tags,#TagId").select2(
{
allowClear: true,
ajax: {
url: "/Entry/ReadSelect2DataMulti",
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term,
page: params.page || 1
};
},
processResults: function (data, params) {
params.page = params.page || 1;
return {
results: data
};
},
cache: true,
error: function (xhr, textStarus, error) {
}
},
minimumInputLength: 2,
placeholder: "აირჩიეთ პოზიცია",
templateResult: function (state) {
var result = '<div class="pos-template">' + '<span title=""><b>' + state.text + '</b></span>';
if (state.content != null && state.content != '') {
var tags = state.content.split(",");
for (i = 0; i < tags.length; i++) {
result = result + '<span class="pos-tag">' + tags[i] + '</span>';
}
} else {
}
result = result + '</div></div>';
return $(result);
},
createSearchChoice: function (term, data) {
if ($(data).filter(function () {
return this.text.localeCompare(term) === 0;
}).length === 0) {
return { id: term, text: term };
}
},
language: {
noResults: function () {
return "პოზიცია ვერ მოიძებნა";
},
inputTooShort: function () {
return "შეავსეთ მინიმიმ 2 სიმბოლო";
},
loadingMore: function () {
return 'იტვირთება...';
},
searching: function () {
return 'იფილტრება...';
}
}
}
);
But this createSearch doesnt do anything.
<div class="form-group">
<select multiple="multiple" class="form-control" id="tags" style="width: 400px;"></select>
</div>
this is my div part . any suggestions ?

I want to show the value of label inside the pie graph. (vue-chartjs / pieceLabel)

I am a student studying vue.
I used Vue-chartjs to draw a graph, and I'd like to display the value on a pie graph.
But I don't know what to do.
Please help me...
the current situation (image) : enter image description here
My wish (image) : enter image description here
Vue.component('pie-chart', {
extends : VueChartJs.Pie,
props: ['data', 'options'],
mounted(){
this.renderPieChart();
},
computed: {
attendanceData : function(){
return this.data
}
},
methods : {
renderPieChart : function(){
this.renderChart(
{
labels: ['a','b','c','d'],
datasets: [{
backgroundColor: ['#10a236', '#f9cd41', '#fe7272', '#5c7add'],
data: [10,20,30,40]
}]
},
{
responsive: true,
maintainAspectRatio: false,
pieceLabel: {
render: 'value',
precision: 1,
}
}
)
}
},
watch : {
attendanceData : function(){
this.$data._chart.destroy();
this.renderPieChart();
}
}
});
As The dicusstion on tooltip of chart.js at Stackoverflow, uses plugin is one solution.
then as Vue chart.js guide said,
in mounted(), uses this.addPlugin to add your plugin like below demo:
Vue.config.productionTip = false
//below plugin is copied from https://stackoverflow.com/a/37989832/5665870
let pluginConfig = {
id: 'my-plugin',
beforeRender: function (chart) {
if (chart.config.options.showAllTooltips) {
// create an array of tooltips
// we can't use the chart tooltip because there is only one tooltip per chart
chart.pluginTooltips = [];
chart.config.data.datasets.forEach(function (dataset, i) {
chart.getDatasetMeta(i).data.forEach(function (sector, j) {
chart.pluginTooltips.push(new Chart.Tooltip({
_chart: chart.chart,
_chartInstance: chart,
_data: chart.data,
_options: chart.options.tooltips,
_active: [sector]
}, chart));
});
});
// turn off normal tooltips
chart.options.tooltips.enabled = false;
}
},
afterDraw: function (chart, easing) {
if (chart.config.options.showAllTooltips) {
// we don't want the permanent tooltips to animate, so don't do anything till the animation runs atleast once
if (!chart.allTooltipsOnce) {
if (easing !== 1)
return;
chart.allTooltipsOnce = true;
}
// turn on tooltips
chart.options.tooltips.enabled = true;
Chart.helpers.each(chart.pluginTooltips, function (tooltip) {
tooltip.initialize();
tooltip.update();
// we don't actually need this since we are not animating tooltips
tooltip.pivot();
tooltip.transition(easing).draw();
});
chart.options.tooltips.enabled = false;
}
}
}
Vue.component('pie-chart', {
extends : VueChartJs.Pie,
props: ['data', 'options'],
mounted(){
this.addPlugin(pluginConfig);
this.renderPieChart();
},
computed: {
attendanceData : function(){
return this.data
}
},
methods : {
renderPieChart : function(){
this.renderChart(
{
labels: ['a','b','c','d'],
datasets: [{
backgroundColor: ['#10a236', '#f9cd41', '#fe7272', '#5c7add'],
data: [10,20,30,40]
}]
},
{
responsive: true,
maintainAspectRatio: false,
pieceLabel: {
render: 'value',
precision: 1
},
showAllTooltips: true
}
)
}
},
watch : {
attendanceData : function(){
//this.$data._chart.destroy();
//this.renderPieChart();
}
}
})
var vm = new Vue({
el: '#app',
data: {
message: 'Hello World'
}
})
<script src="https://unpkg.com/vue#2.5.16/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.min.js"></script>
<script src="https://unpkg.com/vue-chartjs/dist/vue-chartjs.min.js"></script>
<div id="app">
<pie-chart></pie-chart>
</div>

Prop mutating warning in VUE

I got an vue-warning (which results to as an error on my end coz my code is not working) that says:
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "editmode"
With it, tried the suggestion here but can't make it work. Below is my work:
props:{
editmode:{
type: Boolean,
default: false,
}
},
methods:{
toggleM(){
var editmode = this.editmode;
editmode = !editmode;
this.editmode = editmode;
if(editmode == false){
//dothis
}else{
//dothat
}
},
}
TEMPLATE
<template>
<div class="ui-table-container-body">
<div class="ui-table" v-if="Boolean(items.length) || Boolean(Object.keys(items).length)" v-cloak>
<ui-table-body ref="body" v-model="items"
:editmode="editmode"
>
</ui-table-body>
</div>
</div>
</template>
The line this.editmode = editmode; is the one pointed in my console, is there any way I can surpass this?
You must use a data variable as a gateway to your prop.
In your component, the code code should look like this:
props:{
editmode:{
type: Boolean,
default: false,
}
},
data: {
dataEditMode = false
},
watch: {
'editmode': {
handler: 'onEditmodeChanged',
immediate: true,
},
'dataEditMode': {
handler: 'onDataEditModeChanged'
}
},
methods:{
toggleM(){
var editmode = this.dataEditMode;
editmode = !editmode;
this.dataEditMode = editmode;
if(editmode == false){
//dothis
}else{
//dothat
}
},
onEditmodeChanged (newVal) {
this.dataEditMode = newVal
},
onDataEditModeChanged (newVal) {
this.$emit('editmodeChanged', newVal)
}
}
and the the inclusion of this component in your parent-component should look like this:
<my-component-name :editmode="editmode" #editmodeChanged="(e) => { editmode = e }"></my-component-name>
You shouldn't mutate props from the component itself. See the One Way Data Flow section of the guide. You can use a prop as the initial value, and then keep a value in the data section and mutate that:
props: {
editmode: {
type: Boolean,
default: false,
}
},
data () {
return {
emode: this.editmode,
}
},
methods: {
toggleM () {
let editmode = this.emode;
editmode = !editmode;
this.emode = editmode;
if (editmode == false) {
// dothis
} else {
// dothat
}
},
}
Demo
Vue.component('editbox', {
template: '<div>' +
'<button #click="toggleM">{{ btext }}</button>' +
'<input v-if="emode" />' +
'</div>',
props: ['editmode'],
data () {
return {
emode: this.editmode,
}
},
computed: {
btext () {
return this.emode ? "Text" : "Edit";
}
},
methods:{
toggleM() {
this.emode = !this.emode;
},
}
})
var app = new Vue({
el: '#app',
data: {
mode: true,
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<editbox :editmode="mode" />
</div>
I would send back an event to the parent so it could modify its value:
For example (not tested):
Child Component
props:{
editmode:{
type: Boolean,
default: false,
}
},
methods:{
toggleM(){
var editmode = !this.editmode;
this.$emit('changeEditMode', editmode);
if (editmode == false){
//dothis
} else {
//dothat
}
},
}
Parent
<child-component #changeEditMode="editModeChanged" :editmode="editmode"></child-component>
...
methods:{
editModeChanged(value){
this.editmode = value
},
}

How to reload Fuelux Tree with new data

Here i'm trying Fuelux Tree used in Ace admin Template. I have used the same code they have used.
The script code used in ace admin template:
jQuery(function($) {
var tree_data = {};
var sampleData = initiateDemoData(tree_data); //see below
$('#tree1')
.ace_tree({
dataSource: sampleData['dataSource1'],
multiSelect: true,
cacheItems: true,
'open-icon': 'ace-icon tree-minus',
'close-icon': 'ace-icon tree-plus',
'selectable': true,
'selected-icon': 'ace-icon fa fa-check',
'unselected-icon': 'ace-icon fa fa-times',
loadingHTML: '<div class="tree-loading"><i class="ace-icon fa fa-refresh fa-spin blue"></i></div>'
});
function initiateDemoData(tree_data) {
tree_data = {
"2C27D744B956": {
"text": "2C27D744B956",
"children": {
"001B179F4400": {
"text": "9991100003333",
"type": "item"
},
"9991100003333": {
"text": "9991100003333",
"type": "item"
},
"2c27d744b956": {
"text": "9991100003333",
"type": "item"
},
"002170615A04": {
"text": "9991100003333",
"type": "item"
}
},
"type": "folder"
}
};
var dataSource1 = function(options, callback) {
var $data = null
if (!("text" in options) && !("type" in options)) {
$data = tree_data; //the root tree
callback({
data: $data
});
return;
} else if ("type" in options && options.type == "folder") {
if ("children" in options)
$data = options.children || {};
else
$data = {} //no data
}
if ($data != null) //this setTimeout is only for mimicking some random delay
setTimeout(function() {
callback({
data: $data
});
}, parseInt(Math.random() * 500) + 200);
//we have used static data here
//but you can retrieve your data dynamically from a server using ajax call
//checkout examples/treeview.html and examples/treeview.js for more info
}
return {
'dataSource1': dataSource1
}
}
});
Then on a button click i'm trying to refresh the tree, with new data from ajax Get request, But when i tried, an error comes in browser such as "Uncaught TypeError: Cannot read property 'apply' of undefined ".
Following is my ajax code:
$.ajax({
type : "GET",
url : "getDevices.htm?did=" + dID,
success : function(data) {
tree_data = data; //tree_data is the data used for the treeview
$('#tree1').tree('reload');
},
error : function(data) {
console.log("failure" + data);
}
});
Please suggest a method to resolve this issue.
Thanks in advance.

Resources