Menu Form
The menu mock up for Tacofino
by James Doyle
HTML
<h3>New Menu</h3>
<form action="" method="" enctype="multipart/form-data">
<div class="nested" v-for="m in menu">
<label for="">
<strong>Main Category (time or group)</strong>
<input type="text" v-model="m.main_category">
</label>
<p><strong>Special</strong></p>
<div class="nested" v-for="special in m.specials">
<p><strong>Special {{ $index + 1 }}</strong></p>
<label for="">
Day
<input type="text" v-model="special.day">
</label>
<label for="">
Name
<input type="text" v-model="special.name" v-uppercase="special.name">
</label>
<label for="">
Description
<input type="text" v-model="special.description">
</label>
<button type="button" v-if="m.specials.length > 1 && $index > 0" v-on:click.prevent="deleteFromArray(m.specials, $index)">Delete {{ $index + 1 }}</button>
</div>
<button type="button" v-on:click.prevent="addSpecial(m.specials)">Add Special</button>
<p><strong>Menu Items</strong></p>
<div class="nested" v-for="item in m.items">
<p><strong>Group {{ $index + 1 }}</strong></p>
<label for="">
Food Group
<input type="text" v-model="item.food_group">
</label>
<div class="nested" v-for="line in item.items">
<p><strong>Item {{ $index + 1 }}</strong></p>
<label for="">
Name
<input type="text" v-model="line.name" v-uppercase="line.name">
</label>
<label for="">
Description
<input type="text" v-model="line.description">
</label>
<label for="">
Price
<input type="number" v-model="line.price" min="1" max="99">
</label>
<label>
Has Addons
<input type="checkbox" value="1" v-model="line.has_addons">
<br>
<textarea placeholder="Item 3" rows="3" v-if="line.has_addons" v-model="line.addons"></textarea>
</label>
<button...
SCSS
.nested {
border: 2px solid #CCC;
margin-top: -2px;
padding: 1rem 0.5rem;
.nested {
background: rgba(0,0,0,0.04);
}
}
label {
display: inline-block;
width: 100%;
margin: 0.5rem 0;
}
input[type="text"] {
width: 300px;
}
textarea {
width: 300px;
border: 1px solid #CCC;
resize: vertical;
}
JavaScript
Vue.config.debug = true;
Vue.directive('uppercase', {
twoWay: true,
bind: function() {
this.handler = function() {
this.set(this.el.value.toUpperCase());
}.bind(this);
this.el.addEventListener('input', this.handler);
},
unbind: function() {
this.el.removeEventListener('input', this.handler);
}
});
var app = new Vue({
el: 'body',
data: {
menu: [{
main_category: 'Lunch',
specials: [{
day: "Today’s Lunch Special",
name: "FRIED CHICKEN TACO",
description: "soy, sesame, salsa fresca, wakame, ginger, wasabi mayo"
}],
items: [{
food_group: "Appetizers",
items: [{
name: "FRIED CHICKEN TACO",
description: "",
price: 5,
has_addons: false,
addons: ""
}]
}, {
food_group: "Tacos",
items: [{
name: "FISH",
description: "crispy ling cod, cabbage, chipotle mayo, salsa fresca",
price: 6,
has_addons: true,
addons: "Guac 2\nExtra Sauce 2"
}]
}]
}]
},
methods: {
addMenuCategory: function() {
var scaffold = {
main_category: 'New Category',
specials: [{
day: "New Special",
name: "",
description: ""
}],
items: [{
food_group: "Food Group",
items: [{
name: "MENU ITEM",
description: "",
price: 0,
has_addons: false,
addons: ""
}]
}]
};
this.menu.push(scaffold);
},
addMenuItem: function(items) {
var scaffold = {
food_group: "Food Group",
items: [{
name: "MENU ITEM",
description: "",
price: 0,
has_addons: false,
addons: ""
}]
};
items.push(scaffold);
},
deleteFromArray: function(arr, index) {
arr.splice(index, 1);
},
addSpecial:...