I am working on Laravel + spark + vue js. Following is my code
app js
Vue.component('spark-emergency', {
data() {
return {
emergencies:[],
deleteEmergency:[],
editEmergency:[],
editEmergencyForm: new SparkForm({}),
deleteEmergencyForm: new SparkForm({}),
newEmergency: new SparkForm({
name: '',
type: '',
description:''
})
};
},
created() {
this.getEmergencies();
},
methods: {
getEmergencies() {
this.$http.get('/get-emergencies-plan-template')
.then(response => {
this.emergencies = response.data;
});
},
deleteEmergencyPlanTemplateConfirmation(emergency){
this.deleteEmergency = emergency
$('#modal-delete-emergency').modal('show');
},
deleteEmergencyPlanTemplate(){
Spark.delete(`/delete-emergencies-plan-template/${this.deleteEmergency.slug}`, this.deleteEmergencyForm)
.then(() => {
Bus.$emit('updateEmergencies');
$('#modal-delete-emergency').modal('hide');
});
},
createEmergencyPlanTemplate(){
Spark.post('/save-emergency-plan-template', this.newEmergency)
.then(() => {
this.newEmergency.name = '';
this.newEmergency.type = '';
this.newEmergency.description = '';
Bus.$emit('updateEmergencies');
});
},
editEmergencyPlanTemplate(emergency){
this.editEmergency = emergency
$('#modal-edit-emergency').modal('show');
},
updateEmergencyPlanTemplate(){
}
}
});
Blade file
<spark-emergency inline-template>
<div class="spark-screen container">
<div class="row">
<div class="col-md-12">
<!-- create new emergency -->
<div class="panel panel-default">
<div class="panel-heading">Create emergency</div>
<div class="panel-body">
<form class="form-horizontal" role="form"></form>
</div>
</div>
<!-- listing of emergencies -->
<div class="panel panel-default">
<div class="panel-heading">Emergencies Plan Template</div>
<div class="panel-body">
<table class="table table-borderless m-b-none">
<thead>
<th>Name</th>
<th></th>
</thead>
<tbody>
<tr v-for="emergency in emergencies">
<td>
<div class="btn-table-align">
#{{ emergency.name }}
</div>
</td>
<!-- Delete Button -->
<td>
<button class="btn btn-danger-outline" #click="deleteEmergencyPlanTemplateConfirmation(emergency)">
<i class="fa fa-times"></i>
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- Edit Emergency Modal -->
<div class="modal fade" id="modal-edit-emergency" tabindex="-1" role="dialog"></div>
<!-- Delete Emergency Modal -->
<div class="modal fade" id="modal-delete-emergency" tabindex="-1" role="dialog"></div>
</div>
</div>
</div>
</spark-emergency>
Before adding add new and edit logic, it was working perfectly fine but after that Bus.$emit('updateEmergencies'); stopped working and now it is not working.
Any suggestions what can be the reason?
Related
I am using Laravel + VueJS 3 to build a small project,
I use axios.put method for update details for single user in a table row via a modal, but I have problems when I click on submit button of a form inside a modal with axios.put, even I filled all data for all inputs but It still said the errors below, can you guys show me how can I fix this please?
Thanks!
ERROR
My backend:
public function updateUser(Request $req, User $user)
{
$req->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email,' . $user->id,
'password' => 'same:confirmPassword|max:64',
'roles' => 'required',
]);
$input = $req->all();
if (!empty($input['password'])) {
$input['password'] = Hash::make($input['password']);
} else {
$input = Arr::except($input, 'password');
}
$user->update($input);
$user->syncRoles($input['roles']);
return $this->sendResponse($user, 'Updated!');
}
My JS Code:
import axios from "axios";
let API_URL = "http://localhost:8000";
export default {
name: "manageUsers",
components: {},
data() {
return {
users: [],
userInfo: {
id: 0,
name: "",
username: "",
phone: "",
email: "",
password: "",
},
};
},
methods: {
refreshUsers() {
axios.get(`${API_URL}/api/users/allusers`).then((res) => {
this.users = res.data.data;
});
},
getUserInfo(user) {
axios
.get(`${API_URL}/api/users/show/` + user.id)
.then((res) => {
this.userInfo.id = res.data.data.id;
this.userInfo.name = res.data.data.name;
this.userInfo.email = res.data.data.email;
this.userInfo.username = res.data.data.username;
this.userInfo.phone = res.data.data.phone;
})
.catch((error) => {
console.log("ERRRR:: ", error.response.data);
});
},
updateUser() {
axios
.put(`${API_URL}/api/users/update/${this.userInfo.id}`)
.then((res) => {
this.refreshUsers();
alert(res.data);
})
.catch((error) => {
console.log("ERRRR:: ", error.response.data);
});
},
},
mounted() {
this.refreshUsers();
},
};
My VueJS template code:
<template>
<table class="table table-striped" id="datatable">
<tbody>
<tr v-for="(user, id) in users" :key="user.id">
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.email }}</td>
<td>{{ user.username }}</td>
<td class="text-right">
<button
class="btn btn-link btn-warning btn-icon btn-sm"
data-toggle="modal" data-target="#userEditModal"
#click="getUserInfo(user)">
<i class="tim-icons icon-pencil"></i>
</button>
</td>
</tr>
</tbody>
</table>
<!-- EDIT USER MODAL -->
<div class="modal modal-black fade" id="userEditModal" tabindex="-1" role="dialog"
aria-labelledby="userEditModal" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="userEditModal">
Edit user <strong class="text-primary">{{ userInfo.username }}</strong>
</h4>
<button type="button" class="close"
data-dismiss="modal" aria-hidden="true">
<i class="tim-icons icon-simple-remove"></i>
</button>
</div>
<form class="form-horizontal">
<div class="modal-body">
<div class="d-flex flex-row">
<label class="col-md-3 col-form-label">Username</label>
<div class="col-md-9">
<div class="form-group">
<input type="text" class="form-control" name="username"
v-model="userInfo.username" />
</div>
</div>
</div>
<div class="d-flex flex-row">
<label class="col-md-3 col-form-label">Name</label>
<div class="col-md-9">
<div class="form-group">
<input type="text" class="form-control" name="name"
v-model="userInfo.name" />
</div>
</div>
</div>
<div class="d-flex flex-row">
<label class="col-md-3 col-form-label">Email</label>
<div class="col-md-9">
<div class="form-group">
<input type="email" name="email" class="form-control"
v-model="userInfo.email" />
</div>
</div>
</div>
<div class="d-flex flex-row">
<label class="col-md-3 col-form-label">Roles</label>
<div class="col-md-9">
<div class="form-group">
<input type="roles" name="roles" class="form-control"
v-model="userInfo.roles" />
</div>
</div>
</div>
</div>
<div class="modal-footer d-flex flex-row">
<button type="button" class="btn btn-secondary" data-dismiss="modal">
Close
</button>
<button type="submit" class="btn btn-primary" data-dismiss="modal"
#click="updateUser()">
Save changes
</button>
</div>
</form>
</div>
</div>
</div>
<!-- END EDIT USER MODAL -->
</template>```
I think you're not passing any parameters to your put call. axios docs
example:
axios.put('https://httpbin.org/put', { hello: 'world' });
When an issue like this arises you can always check your network tab in your browser. to see what data is send to your server.
I have tried to use export default and export default legend but it still got error
The requested module '/src/legends.js?t=1637071' does not provide an export named 'legend'
in console log, how can I fix this problem?
Thank you!!
legends.js
import axios from "axios";
const API_URL = "http://localhost:8000/api";
function add(url, type) {
axios
.post(`${API_URL}/${url}`, this.newRole)
.then((res) => {})
.catch((error) => {
console.log("ERRRR:: ", error.response.data);
});
}
function remove(url, type) {
axios
.post(`${API_URL}/${url}`, this.newRole)
.then((res) => {})
.catch((error) => {
console.log("ERRRR:: ", error.response.data);
});
}
export default legend
manageRoles.vue
<template>
<div class="col-md-12">
<div class="card">
<div class="card-header d-flex flex-row">
<h4 class="card-title align-self-center">Roles Manager</h4>
<button
class="btn btn-success btn-fab btn-icon btn-round mb-3 ml-2"
data-toggle="modal"
data-target="#addRoleModal">
<i class="icon-simple-add"></i>
</button>
</div>
<div class="card-body">
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>Role Name</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="role in roles" :key="role.id">
<td>
{{ role.id }}
</td>
<td>
{{ role.name }}
</td>
<Buttons />
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- MODALS -->
<!-- ADD NEW ROLE MODAL -->
<div
class="modal modal-black fade" id="addRoleModal"
tabindex="-1" role="dialog" aria-labelledby="addRoleModal" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Add new role</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
<i class="icon-simple-remove"></i>
</button>
</div>
<form class="form-horizontal">
<div class="modal-body">
<div class="d-flex flex-row">
<label class="col-md-4 col-form-label">Role name</label>
<div class="col-md-6">
<div class="form-group">
<input type="name" name="name" class="form-control"
v-model="newRole.name" />
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">
Cancel
</button>
<button type="submit" class="btn btn-primary" #click.stop.prevent="addRole()">
Add new role
</button>
</div>
</form>
</div>
</div>
</div>
<!-- END ADD NEW ROLE MODAL -->
<!-- REMOVE ROLE MODAL -->
<div class="modal modal-black fade" id="roleRemoveModal"
tabindex="-1" role="dialog" aria-labelledby="roleRemoveModal" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="roleRemoveModal">
Confirm delete role
<strong class="text-primary">
{{ roleInfo.name }}
</strong>
</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
<i class="icon-simple-remove"></i>
</button>
</div>
<div class="modal-body h4 text-white text-center mt-4">
Really want to delete role
<strong class="text-danger">
{{ roleInfo.name }}
</strong>?
</div>
<div class="modal-footer d-flex flex-row">
<button type="button" class="btn btn-secondary" data-dismiss="modal">
Cancel
</button>
<button type="button" class="btn btn-danger" data-dismiss="modal" #click="removeRole()">
Delete role
</button>
</div>
</div>
</div>
</div>
<!-- END REMOVE ROLE MODAL -->
<!-- END MODALS -->
</template>
<script>
import Buttons from "../components/cores/Buttons.vue";
import { legend } from "/src/legends.js";
export default {
name: "manageRoles",
components: { Buttons },
data() {
return {
roles: [],
newRole: {
name: null,
},
roleInfo: {
id: 0,
name: "",
},
};
},
methods: {
addRole() {
legend.add(`roles/createRole`);
this.$router.push("/manager/roles");
},
removeRole() {
legend.remove(`roles/createRole`);
this.$router.push("/manager/roles");
},
},
mounted() {
this.refreshRoles();
},
};
</script>
export default is default export, as the name implies. Regardless of how the variable that holds a value of default export is called, it's supposed to be imported as default import, not named import with brackets:
const legend = ...;
export default legend;
and
import legendCanBeImportedUnderAnyName from "/src/legends.js"
Alternatively, it can be made named export, it also needs to be imported as such:
export const legend = ...;
and
import { legend } from "/src/legends.js"
Try this.import * as legend from "/src/legends.js";
I have 2 pages, one has a list of products and the other one has a bunch of data for that product. There is also a drop-down in the second page.
The problem I'm having is that I'm struggling to get the drop-down to have the selected product selected.
So for example, if I select product 1 from the first page then on the second page the drop-down will show product 1 and if I select product 2 then the drop-down will show product 2.
Here is my code for productIndex.vue
<template>
<div>
<div class="content-header">
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">Product Index</h3>
</div>
<div class="card-body p-0">
<table class="table table-sm table-hover">
<thead>
<tr>
<th>ID</th>
<th>Product Name</th>
<th style="width: 180px;"></th>
</tr>
</thead>
<tbody>
<tr v-for="product in products">
<td>{{ product.id }}</td>
<td>{{product.name}}</td>
<td class="text-right">
<a #click="goToProductData(product.id)" class="btn btn-xs btn-primary">
Data
</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['products'],
data() {
return {
}
},
methods: {
goToProductData(product_id){
localStorage.setItem('product', product_id);
window.location = `/product-data`;
}
},
}
</script>
and here is my productData.vue
<template>
<div>
<div class="content-header">
<div class="container">
<div class="card">
<div class="card-body">
<div class="row mb-2">
<div class="col-sm-6">
<label for="product_id_select">Product</label>
<select id="product_id_select" class="form-control select2" style="width: 100%;">
<optgroup v-for="product in selectProducts" :label="customer.text">
<option v-for="p in product.children" :value="p.id">{{ p.text }}</option>
</optgroup>
</select>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['products'],
data() {
return {
}
},
computed: {
selectProducts() {
let select2Options = [];
Object.keys(this.products).forEach(product => {
let productOptions = [];
this.products[product].forEach(p => {
productOptions.push({ id: p.id, text: p.name });
});
select2Options.push({
text: product,
children: productOptions
});
});
return select2Options;
}
}
}
</script>
You forgot to add the v-model to the select in the second page. You can find some example here.
Your code should be something like:
<select id="product_id_select" v-model="selectedProductId" class="form-control select2" style="width: 100%;">
where selectedProductId is a value in your data (or a computed property) that contains the value inserted into the local storage in the first page
I want to use the same component twice from a parent component; all that was stopping me was the use of an ID for a dropdown in the subcomponents! So I currently have duplicated the subcomponent.
My parent component:
<template>
<div id="compare-page">
<div class="row">
<div class="col-md-12">
<div class="row campaign-overview">
<div class="col-md-4">
<h2>{{ campaign.name }}</h2>
<strong>Published</strong>
<strong>Starts: {{ campaign.start_date }} - Ends: {{ campaign.end_date }}</strong>
</div>
<div class="col-md-4 text-right">
<select name="daterange" id="" #change="onChangeDaterange($event)">
<option v-for="(daterange, index) in dateranges" v-bind:key="daterange.index" :value="index" :data-start="daterange.start" :data-end="daterange.end" :selected="daterange.optionSelected == 1">{{ index }}</option>
</select>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<left-device ref="leftDevice"></left-device>
</div>
<div class="col-md-6">
<right-device ref="rightDevice"></right-device>
</div>
</div>
</div>
</template>
<script>
import left from './compared_device_component_left.vue';
import right from './compared_device_component_right.vue';
export default {
components: {
'left-device': left,
'right-device': right,
},
mounted() {
this.fetchCampaignData().then(result => {
});
},
data() {
return {
campaign_id: this.$route.params.campaign_id,
campaign: [],
dateranges: [],
leftDevice: '',
rightDevice: ''
}
},
methods: {
fetchCampaignData() {
return this.$http.get('/api/portal/campaign/' + this.campaign_id + '/campaign?' + this.axiosParams)
.then(function(data){
return data.json();
}).then(function(data){
this.campaign = data.campaign;
this.dateranges = data.dateranges;
});
},
onChangeDaterange(event) {
this.$router.push('?range=' + event.target.value);
this.$refs.leftDevice.onChangeDaterange(event);
this.$refs.rightDevice.onChangeDaterange(event);
},
},
computed: {
axiosParams() {
const params = new URLSearchParams();
if(this.$route.query.range) params.append('range', this.$route.query.range);
return params;
}
},
}
</script>
<style lang="scss">
</style>
One of my subcomponents
<template>
<div>
<div class="row device-overview">
<div class="col-md-4">
<select name="devices" id="deviceLeft" #change="onChangeDevice($event)">
<option v-for="(device, index) in devices" v-bind:key="device.index" :value="index" :data-device_id="device.device_id" :data-address="device.address" :selected="device.optionSelected == 1">{{ device.device_id }} | {{ device.address }}</option>
</select>
</div>
</div>
<div class="row totals">
<div class="col-md-4 card">
<div class="card-body">
<h5 class="card-title">Total Interactions</h5>
<p class="card-text">{{ total_interactions }}</p>
</div>
</div>
<div class="col-md-4 card">
<div class="card-body">
<h5 class="card-title">Average Interactions Per Day</h5>
<p class="card-text">{{ average_daily_interactions }}</p>
</div>
</div>
<div class="col-md-4 card">
<div class="card-body">
<h5 class="card-title">Total Average Dwell Time</h5>
<p class="card-text">{{ average_dwell_time }}s</p>
</div>
</div>
</div>
<div class="row interactions">
<div class="col-md-12">
<h5>Total Interactions Per Product</h5>
<table class="table table-condensed table-hover">
<tbody>
<tr>
<td class="">Tag</td>
<td class="">Mapped Product</td>
<td class="">Lifts</td>
</tr>
<tr v-for="interaction in table_product_interactions">
<td class="">{{ interaction.tag }}</td>
<td class="">{{ interaction.mapping }}</td>
<td>{{ interaction.tag_count }}</td>
</tr>
</tbody>
</table>
</div>
<div class="col-md-12">
<h5>Total Interactions Per Day</h5>
<div class="chart" ref="chartdaily"></div>
</div>
</div>
<div class="row interactions">
<div class="col-md-8">
<h5>Total Interactions Per Hour</h5>
<div class="chart" ref="charthourly"></div>
</div>
</div>
</div>
</template>
<script>
import * as am4core from "#amcharts/amcharts4/core";
import * as am4charts from "#amcharts/amcharts4/charts";
import am4themes_animated from "#amcharts/amcharts4/themes/animated";
am4core.useTheme(am4themes_animated);
export default {
mounted() {
this.fetchData(null).then(result => {
this.chartTotalPerDay();
this.chartTotalPerHour();
});
},
data() {
return {
campaign_id: this.$route.params.campaign_id,
campaign: [],
dateranges: [],
device: [],
devices: [],
total_interactions: '',
average_daily_interactions: '',
average_dwell_time: '',
interaction_type: '',
chart_daily_interactions: [],
chart_hourly_interactions: [],
table_product_interactions: []
}
},
methods: {
fetchData(deviceID) {
// Use JS to get by ID!
var device = document.getElementById("deviceLeft");
// ... call to API
},
chartTotalPerDay() {
// ...
},
chartTotalPerHour() {
// ...
},
onChangeDaterange(event) {
// Use JS to get by ID!
var device = document.getElementById("deviceLeft");
// st cookie
document.cookie = "deviceLeft="+device.value;
this.fetchData(device.value).then(result => {
this.chartTotalPerDay();
this.chartTotalPerHour();
});
},
onChangeDevice(event) {
// st cookie
document.cookie = "deviceLeft="+event.target.value;
this.fetchData(event.target.value).then(result => {
this.chartTotalPerDay();
this.chartTotalPerHour();
});
}
},
created() {
},
computed: {
axiosParams() {
const params = new URLSearchParams();
if(this.$route.query.range) params.append('range', this.$route.query.range);
return params;
}
},
filters: {
},
directives: {
},
}
</script>
<style lang="scss">
.interactions {
h5 {
text-align: center;
}
}
.chart {
min-height: 550px;
}
</style>
I am currently using
var device = document.getElementById("deviceLeft");
...in my duplicated left/right subcomponents (this is 'left' and I also have 'right').
Should I use a 'ref' for my devices dropdown, so that each instance of the subcomponent is looking at the devices dropdown relative to that instance? Currently if I merge these into one the devices dropdown ID is the same for both instances and therefore I get incorrect ID in one of the instances!
Any helpful pointers would be much appreciated.
Thanks,
K...
I'm fetching data into the table and on clicking any table row it open a nested colspan inside table row.
I want to close previous table row if i click on another table row (Like accordion does )
This is my Vue File
{{index+1}}
{{statement.paper_quality_id.paper_quality}} -
{{statement.paper_size_id.length}} X {{statement.paper_size_id.width}} -
{{statement.paper_brand_id.paper_brand}} -
{{statement.thickness}}
{{Math.ceil((statement.in_total_before - statement.total_out_before)/500)}}
<td>
<div class="row">
<div
class="col-md-4 text-center"
>{{Math.floor((statement.total_sheets_in_range)/500)}}</div>
<div
class="col-md-4 text-center"
>{{Math.floor((statement.total_sheets_in_range)%500)}}</div>
</div>
</td>
<td>
<div class="row">
<div
class="col-md-4 text-center"
>{{Math.floor((statement.total_outward_range)/500)}}</div>
<div
class="col-md-4 text-center"
>{{Math.floor((statement.total_outward_range)%500)}}</div>
</div>
</td>
<td>
<div class="row">
<div class="col-md-4 text-center">
{{
Math.floor((((statement.in_total_before - statement.total_out_before) + (statement.total_sheets_in_range)) - statement.total_outward_range)/500)
}}
</div>
<div class="col-md-4 text-center">
{{
Math.floor((((statement.in_total_before - statement.total_out_before) + (statement.total_sheets_in_range)) - statement.total_outward_range)%500)
}}
</div>
</div>
</td>
</tr>
<tr :id="'show_'+index" style="display : none">
<td colspan="6">
<table class="table table-hover">
<tr>
<th>Date</th>
<th>Opening</th>
<th>Inward</th>
<th>Outward</th>
<th>Balance</th>
</tr>
<tr v-for="(_statement,index) in statements_details">
<td>{{_statement.date}}</td>
<td>
<div class="row">
<div
class="col-md-3 text-center"
>{{Math.ceil((_statement.opening.total_in - _statement.opening.total_out)/500)}}</div>
<div
class="col-md-3 text-center"
>{{Math.ceil((_statement.opening.total_in - _statement.opening.total_out)%500)}}</div>
</div>
</td>
<td>
<div class="row">
<div class="col-md-3 text-center">{{Math.ceil((_statement.inward)/500)}}</div>
<div class="col-md-3 text-center">{{Math.ceil((_statement.inward)%500)}}</div>
</div>
</td>
<td>
<div class="row">
<div
class="col-md-3 text-center"
>{{Math.ceil((_statement.outward)/500)}}</div>
<div
class="col-md-3 text-center"
>{{Math.ceil((_statement.outward)%500)}}</div>
</div>
</td>
<td>
<div class="row">
<div
class="col-md-3 text-center"
>{{Math.ceil((_statement.outward)/500)}}</div>
<div
class="col-md-3 text-center"
>{{Math.ceil((_statement.outward)%500)}}</div>
</div>
</td>
</tr>
</table>
</td>
</tr>
</tbody>
This is my js file
PostLedgerID(e) {
e.preventDefault();
const AccountDetail = {
id: this.id,
start_date: this.start_date + ' 00:00:00.957761',
end_date: this.end_date + ' 00:00:00.957761'
}
var vm = this;
axios.post('/Statement/', AccountDetail)
.then((response) => {
console.log(response)
vm.statements = response.data;
}).catch((err) => {
console.log(err)
});
},
//Show Hide Nested Table
statementDetail(rowid, paper_id, brand_id, size_id, thickness) {
const userDetail = {
account_access_key_id: $('#ledger_id').val(),
start_date: this.start_date + ' 00:00:00.957761',
end_date: this.end_date + ' 00:00:00.957761',
paper_quality_id: paper_id,
paper_brand_id: brand_id,
paper_size_id: size_id,
thickness: thickness
}
axios.post('/StatementDetail/', userDetail)
.then((response) => {
console.log(userDetail)
$('#show_' + rowid).toggle();
this.statements_details = response.data;
}).catch((err) => {
console.log(err)
});
}