Reputation: 129
On parent I have:
<template>
<b-container>
<b-modal id="uw-qb-add-item-modal"
ref="uw-qb-add-item-modal"
title="Enter Item Number"
@ok="handleNewItem">
<form @submit.stop.prevent="handleSubmit">
<b-form-input type="text"
placeholder="Enter the item number" />
</form>
</b-modal>
<div class="row mb-3">
<div class="col">
<nuxt-link to="/">
<i class="fa fa-chevron-left" aria-hidden="true"></i>
Quote Build List
</nuxt-link>
</div>
</div>
<div class="row mb-3">
<div class="col-md"><h2>Quote Build <b-badge :variant="buildBadgeVariant">{{ buildBadgeText }}</b-badge></h2></div>
<div class="col-md text-right text-success"><h3><i class="fa fa-usd" aria-hidden="true"></i> {{ buildTotal | formatDollars }}</h3></div>
</div>
<div class="row mb-3">
<div class="col-md form-group">
<build-customer :buildNumber="buildNumber"/>
</div>
<div class="col-md form-group">
<build-address :buildNumber="buildNumber" />
</div>
<div class="col-md form-group">
<build-contact :buildNumber="buildNumber" />
</div>
<div class="col-md form-group">
<label for="uw-qb-due-date">Due Date</label>
<date-picker v-model="dueDate"/>
</div>
</div>
<div class="row mb-3">
<div class="col-sm form-group">
<div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" v-model="internal" />
Internal Quote
</label>
</div>
<build-requester-id v-if="internal" :buildNumber="buildNumber"/>
</div>
<div class="col-sm form-group">
<label>RFQ Number</label>
<b-form-input type="text" v-model="rfqNumber"/>
</div>
<div class="col-sm form-group">
<div class="form-check">
<label class="form-check-label mb-3">
<input class="form-check-input" type="checkbox" v-model="update" />
Quote Update
</label>
<label class="form-check-label">
<input class="form-check-input" type="checkbox" v-model="correctiveAction" />
Corrective Action
</label>
</div>
</div>
<div class="col-sm form-group">
<label>Request Date</label>
<date-picker v-model="requestDate" />
</div>
</div>
<div class="row mb-3">
<div class="col-md text-right">
<b-btn variant="primary"
v-b-toggle="editId"
@click="newEditItem">
<i class="mr-1 fa fa-plus" aria-hidden="true"></i>
Add Item
</b-btn>
</div>
</div>
<b-collapse :id="editId">
<build-item-edit @doOnEmit="expand" :buildNumber="buildNumber"
:itemNumber="editItemNumber"/>
</b-collapse>
<build-item-list @edit="edit" :buildNumber="buildNumber" />
<build-breakdown-edit :buildNumber="buildNumber" :breakdownNumber="editBreakdownNumber"/>
<build-breakdown-list :buildNumber="buildNumber"/>
</b-container>
</template>
<script>
import BuildCustomer from '@/components/buildCustomer'
import BuildAddress from '@/components/buildAddress'
import BuildContact from '@/components/buildContact'
import BuildRequesterId from '@/components/buildRequesterId'
import BuildItemEdit from '@/components/buildItemEdit'
import BuildItemList from '@/components/buildItemList'
import BuildBreakdownEdit from '@/components/buildBreakdownEdit'
import BuildBreakdownList from '@/components/buildBreakdownList'
import DatePicker from '@/components/datePicker'
export default {
data () {
return {
editItemNumber: null,
editBreakdownNumber: null
}
},
components: {
'build-customer': BuildCustomer,
'build-address': BuildAddress,
'build-contact': BuildContact,
'build-requester-id': BuildRequesterId,
'build-item-edit': BuildItemEdit,
'build-item-list': BuildItemList,
'build-breakdown-edit': BuildBreakdownEdit,
'build-breakdown-list': BuildBreakdownList,
'date-picker': DatePicker
},
computed: {
// nextItemNumber () {
// const itemNumbers = this.$store.getters['build/item/numbers'](this.buildNumber)
// return Math.min.apply(null, itemNumbers) - 1
// },
editId () {
return this.idGen('edit-item-collapse')
},
dueDate: {
get () {
return this.build.dueDate
},
set (value) {
this.$store.commit('build/setDueDate', { buildNumber: this.buildNumber, dueDate: value })
}
},
requestDate: {
get () {
return this.build.requestDate
},
set (value) {
this.$store.commit('build/setRequestDate', { buildNumber: this.buildNumber, requestDate: value })
}
},
internal: {
get () {
return this.build.internal
},
set (value) {
this.$store.commit('build/setInternal', { buildNumber: this.buildNumber, internal: !!value })
}
},
update: {
get () {
return this.build.update
},
set (value) {
this.$store.commit('build/setUpdate', { buildNumber: this.buildNumber, update: !!value })
}
},
correctiveAction: {
get () {
return this.build.correctiveAction
},
set (value) {
this.$store.commit('build/setCorrectiveAction', { buildNumber: this.buildNumber, correctiveAction: !!value })
}
},
requesterId: {
get () {
return this.build.requesterId
},
set (value) {
if (value === null || this.$store.getters.employees.hasOwnProperty(value)) {
this.$store.commit('build/setRequesterId', { buildNumber: this.buildNumber, requesterId: value })
}
}
},
rfqNumber: {
get () {
return this.build.rfqNumber
},
set (value) {
this.$store.commit('build/setRfqNumber', {buildNumber: this.buildNumber, rfqNumber: value })
}
},
employees () {
const res = [{ value: null, text: 'Select requested by ...' }];
for (var empId in this.$store.getters['employee/employees']) {
res.push({ value: empId, text: this.$store.getters.employees[empId] });
}
return res;
},
buildNumber () {
return parseInt(this.$route.params.buildNumber, 10);
},
build () {
return this.$store.getters['build/build'](this.buildNumber);
},
buildBadgeVariant () {
if (this.isNewBuild) { return 'primary'; }
return 'info';
},
buildBadgeText () {
if (this.isNewBuild) { return 'New'; }
return this.buildNumber;
},
isNewBuild () {
return this.buildNumber < 0;
},
buildTotal () {
return this.$store.getters['build/total'](this.buildNumber);
}
},
methods: {
fetchData () {
if (!this.isNewBuild) {
// TODO - waiting on schema changes
console.log('Fetching build data for ' + this.$route.params.buildNumber);
}
},
handleNewItem () {
this.$store.commit('setError', 'Adding items not supported');
},
newEditItem () {
this.editItemNumber = this.nextItemNumber
},
edit(eventPayload) {
this.editItemNumber = eventPayload
},
expand() {
console.log("TEST")
this.idGen('edit-item-collapse')
}
},
fetch (context) {
const buildNumber = parseInt(context.params.buildNumber, 10)
const build = context.store.getters['build/build'](buildNumber)
if (build === null && buildNumber >= 0) {
console.log('load build')
} else if (build === null && buildNumber < 0) {
// if the build doesn't exist and it is a temp build
// number, then just redirect to new
context.app.router.replace('/new')
}
}
}
</script>
buildItemEdit
<template>
<b-container>
<b-row>
<b-col>
<h3>Item</h3>
<p></p>
<b-row></b-row>
<p></p>
</b-col>
</b-row>
<b-row>
<b-col>
<b-row>
<b-col>
<label>Item No.</label>
<b-form-input v-model='itemNum' type="text" :state="itemNoState" onkeypress='return event.charCode >= 48 && event.charCode <= 57'
/>
</b-col>
<b-col>
<label>Item Type</label>
<b-form-select v-model="type" :options="itemTypes" class="mb-3" :state="itemTypeState" />
</b-col>
<b-col>
<label>Part No.</label>
<b-form-input v-model='partNumber' type="text" :state="partNoState" onkeypress='return event.charCode >= 48 && event.charCode <= 57'
/>
</b-col>
<b-col>
<label>Piece Amount</label>
<b-form-input v-model='pieceCount' type="number" :state="pieceAmountState" onkeypress='return event.charCode >= 48 && event.charCode <= 57'
/>
</b-col>
</b-row>
<b-row>
<b-col>
<label>Comments</label>
<b-form-textarea id="comments" v-model="comments" placeholder="Enter comments here" :rows="3" :max-rows="6"></b-form-textarea>
</b-col>
</b-row>
<p></p>
<b-row>
<b-col>
<b-card-group deck class="mb-3">
<b-card bg-variant="primary" text-variant="white" class="text-center">
<p class="card-text">Breakdown 1</p>
</b-card>
<b-card bg-variant="secondary" text-variant="white" class="text-center">
<p class="card-text">Breakdown 2</p>
</b-card>
<b-card bg-variant="success" text-variant="white" class="text-center">
<p class="card-text">Breakdown 3</p>
</b-card>
</b-card-group>
</b-col>
</b-row>
</b-col>
</b-row>
<b-row>
<p></p>
</b-row>
<b-row>
<p></p>
</b-row>
<b-row>
<b-col>
<div v-if="editmsg" class="col-md text-left">
<b-btn size="" @click="editUpdate" variant='success'>
<i class='mr-1 fa fa-plus' aria-hidden="true"></i> Save Edit</b-btn>
</div>
<p></p>
</b-col>
<b-col>
<div class="col-md text-center">
<b-btn size="" @click="addItem" variant='primary'>
<i class='mr-1 fa fa-plus' aria-hidden="true"></i> Break Downs</b-btn>
</div>
</b-col>
<b-col>
<div class="col-md text-right">
<b-btn size="" @click="addItem" variant='primary' v-bind:disabled="!canSave">
<i class='mr-1 fa fa-plus' aria-hidden="true"></i> Save Item</b-btn>
</div>
</b-col>
</b-row>
<div v-if="existmsg">
<p></p>
<b-alert show variant="danger">{{ existmsg }}</b-alert>
</div>
<div v-if="editmsg">
<p></p>
<b-alert show variant="warning">{{ editmsg }}</b-alert>
</div>
</b-container>
</template>
<script>
import Util from '@/lib/util'
export default {
props: ['buildNumber', 'itemNumber'],
data() {
return {
itemNum: "",
type: "",
partNumber: "",
pieceCount: "",
comments: "",
selected: "A",
}
},
watch: {
itemNumber: function (editItemNumber) {
if (editItemNumber == null) {
this.update({})
} else {
const item = this.item(editItemNumber)
this.update(item)
this.itemNum = editItemNumber
}
}
},
computed: {
itemNoState() {
return !isNaN(parseFloat(this.itemNum)) && isFinite(this.itemNum) ? null : false;
},
itemTypeState() {
return (this.type) ? null : false;
},
partNoState() {
return !isNaN(parseFloat(this.partNumber)) && isFinite(this.partNumber) ? null : false;
},
pieceAmountState() {
return !isNaN(parseFloat(this.pieceCount)) && isFinite(this.pieceCount) ? null : false;
},
canSave() {
return this.itemNumber != '' && this.type != '' && this.partNumber != '' && this.pieceCount != ''
},
editmsg: {
get() {
return this.$store.getters["build/item/editmsg"];
},
set(value) {
this.$store.commit("build/item/seteditmsg", value);
}
},
existmsg: {
get() {
return this.$store.getters["build/item/existmsg"];
},
set(value) {
this.$store.commit("build/item/setexistmsg", value);
}
},
itemTypes() {
const iTypes = []
const b = this.$store.getters['itemType/all']
for (var itemValue in b) {
iTypes.push({
value: itemValue,
text: b[itemValue]
})
}
return iTypes
}
},
methods: {
item(itemNumber) {
return this.$store.getters["build/item/item"](
this.buildNumber,
itemNumber
);
},
addItem() {
if (this.item(this.itemNum) == null)
{
this.$store.commit('build/item/add', {
buildNumber: this.buildNumber,
itemNumber: this.itemNum,
item: {
type: this.type,
partNumber: this.partNumber,
pieceCount: this.pieceCount,
comments: this.comments
}
})
this.update({})
}
else
{
this.existmsg = "Item number " + this.itemNum + " already exists on this quote"
}
},
update(item) {
this.itemNum = Util.field(item, 'itemNumber', '')
this.type = Util.field(item, 'type', '')
this.partNumber = Util.field(item, 'partNumber', '')
this.pieceCount = Util.field(item, 'pieceCount', '')
this.comments = Util.field(item, 'comments', '')
this.existmsg = ""
},
editUpdate(item) {
this.$store.commit('build/item/update', {
buildNumber: this.buildNumber,
itemNumber: this.itemNum,
item: {
type: this.type,
partNumber: this.partNumber,
pieceCount: this.pieceCount,
comments: this.comments
}
})
this.update({})
this.editmsg = ""
}
}
}
</script>
Now on the child I already have a button that emits an item number to the parent (editItemNumber
) above. But I always want that same button on the child to expand this collapse on the parent only if its not collapsed.
Below is the existing child.
edit(item) {
const payload = {
item
};
this.$emit('edit', item.itemNumber);
this.editmsg = "Edit your item above and then click 'Save Edit'"
}
buildItemList
<template>
<b-container>
<div>
<p></p>
<h5>Items</h5>
<p></p>
<b-table show-empty bordered striped hover :items="itemTableList" :fields="fields">
<template slot="actions" scope="row">
<b-btn variant='success' size="sm" v-on:click="edit(row.item,$event.target)">Edit</b-btn>
<b-btn variant='danger' size="sm" @click.stop="delRow(row.item,row.index,$event.target)">Delete</b-btn>
</template>
</b-table>
</div>
</b-container>
</template>
<script>
import Util from "@/lib/util";
export default {
data() {
return {
fields: [
{ key: "itemNumber", label: "Item No.", sortable: true },
{ key: "type", label: "Item Type", sortable: false },
{ key: "partNumber", label: "Part No.", sortable: false },
{ key: "pieceCount", label: "Piece Amount", sortable: false },
{ key: "comments", label: "Comments", sortable: false },
{ actions: { label: "Actions" } }
]
};
},
props: ["buildNumber"],
computed: {
itemNumbers() {
console.log("DEVELOPER")
console.log(this.buildNumber)
const items = this.$store.getters["build/item/items"](this.buildNumber);
return Util.numSortedKeys(items);
},
itemTableList() {
const itemList = [];
for (var i of this.itemNumbers) {
const item = this.item(i);
itemList.push({
itemNumber: i,
type: item.type,
partNumber: item.partNumber,
pieceCount: item.pieceCount,
comments: item.comments
});
}
return itemList;
},
editmsg: {
get() {
return this.$store.getters["build/item/editmsg"];
},
set(value) {
this.$store.commit("build/item/seteditmsg", value);
}
}
},
methods: {
item(itemNumber) {
return this.$store.getters["build/item/item"](
this.buildNumber,
itemNumber
);
},
edit(item) {
const payload = {
item
};
this.$emit('doOnEmit')
this.$emit('edit', item.itemNumber);
// this.editmsg = "Edit your item above and then click 'Save Edit'"
}
}
};
</script>
So to reiterate, when the button edit
is clicked, beyond what it's currently doing I want to expand that toggle collapse if not expanded on the parent component.
Is that possible?
Upvotes: 0
Views: 845
Reputation: 15934
I assume <build-item-edit>
is your own component so just add a callback event to it i.e
<build-item-edit @doOnEmit="someFunctionOnTheParent" :buildNumber="buildNumber" :itemNumber="editItemNumber"/>
Then on the parent component, define the method someFunctionOnTheParent
and run the code that does your UI stuff.
Then in the build-item-edit
component, before you emit the value, call this.$emit('doOnEmit')
Upvotes: 2