I want to create a activate/deactive button in vue - javascript

This is my table. As you can see I have added a button to perform an action.
The action needs to change active to not active and not active to active upon clicking.
I cannot seem to find the SQL area that I could access which makes it difficult for me to update the database upon clicking. Any suggestions or help will be highly appreciated.
If there is any way to update the database upon clicking this button and then the new value should also appear in the datatable.
<table class="table" id="myTable">
<thead>
<tr>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr v-for="product in filteredProducts" :key="product.id">
<td>{{ product.status }}</td>
<td>
<div class="btn-group" role="group">
<button class="btn btn-secondary" #click="acdcProduct(product.id)">Active/Deactive</button>
</div>
</td>
</tr>
</tbody>
</table>
Here is what I have tried to do so far. Sorry I am new to vue.js
acdcProduct(id) {
this.axios
.acdc(`http://localhost:8000/api/products/${id}`)
let i = this.products.map(data => data.id).indexOf(id);
this.products.status(i, active)
}

Example for vue side, you should also check if database update was succesfull :
new Vue({
el: '#demo',
data() {
return {
products: [
{id: 1, name: 'prod 1', status: false},
{id: 2, name: 'prod 2', status: false},
{id: 3, name: 'prod 3', status: false},
{id: 4, name: 'prod 4', status: false},
{id: 5, name: 'prod 5', status: false},
]
}
},
methods: {
acdcProduct(id) {
/*this.axios
.acdc(`http://localhost:8000/api/products/${id}`)*/
let i = this.products.map(data => data.id).indexOf(id);
this.products[i].status = !this.products[i].status
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<table class="table" id="myTable">
<thead>
<tr>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr v-for="product in products" :key="product.id">
<td>{{ product.status ? 'active' : 'deactive' }}</td>
<td>
<div class="btn-group" role="group">
<button class="btn btn-secondary"
#click="acdcProduct(product.id)"
>
Active/Deactive
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>

let filteredProducts is an array in first time it has all data of product and after update product data you have a array of update products in response and again update the filteredProducts array with new updated data.
let filteredProducts = [];
acdcProduct(id) {
axios({
method: "PUT",
url: `http://localhost:8000/api/products/${id}`,
}).then((res) => {
filteredProducts = res.data
});
}

Related

How can I create a Vue table component with column slots?

I am currently working with a relatively large Vue (Vue 2) project that uses a lot of tables, and I want to create a reusable table component where each column is a child component / slot. Something like this:
<Table :data="data">
<TableColumn field="id" label="ID" />
<TableColumn field="name" label="Name" />
<TableColumn field="date_created" label="Created" />
</Table>
const data = [
{ id: 1, name: 'Foo', date_created: '01.01.2021' },
{ id: 2, name: 'Bar', date_created: '01.01.2021' }
];
Which in turn should output this:
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Created</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Foo</td>
<td>01.01.2021</td>
</tr>
<tr>
<td>2</td>
<td>Bar</td>
<td>01.01.2021</td>
</tr>
</tbody>
</table>
We've previously used Buefy, but the vendor size becomes unnecessarily large, as we only use a fraction of the components' functionality - so I want to create a lightweight alternative.
With this data you only need 2 Props, labels and data.
<!-- Component -->
<table>
<thead>
<tr>
<td v-for="(label, labelIndex) in labels" :key="labelIndex">
{{ label.text }}
</td>
</tr>
</thead>
<tbody>
<tr v-for="(item, itemIndex) in data" :key="itemIndex">
<td v-for="(label, labelIndex) in labels" :key="labelIndex">
{{ item[label.field] }}
</td>
</tr>
</tbody>
</table>
// Data and labels
const labels = [
{ text: ID, field: id },
{ text: Name, field: name },
{ text: Created, field: date_created },
]
const data = [
{ id: 1, name: 'Foo', date_created: '01.01.2021' },
{ id: 2, name: 'Bar', date_created: '01.01.2021' }
];
<table-component
:labels="labels"
:data="data"
>
</table-component>
If you need something more complex you can use nested components combined with a named slots for the header or footer of the table (or other options like search).

ERROR TypeError: Cannot read property 'name' of undefined when i try to add product

I try to make a basket as simply as possible, I try to add a product to my basket but I have an error but I cannot find my error.
thank you
html
<h2>Product</h2>
<div class="card" *ngFor="let product of productList">
<h1>{{product.name}}</h1>
<p class="price">{{product.price | currency: 'USD'}}</p>
<p><button (click)=add()>Add to Cart</button></p>
</div>
</div>
<div>
<h2>Total</h2>
<div class="card">
<table>
<thead>
<tr>
<th>product</th>
<th>price</th>
<th>Quantity</th>
<th>total</th>
</tr>
</thead>
<tbody *ngFor="let added of productArray">
<tr>
<td>{{added.name}}</td>
<td>{{added.price}}</td>
<td>x 10</td>
<td>45€</td>
ts.file
productList = [
{ name: 'Louis Vuis', price: 10 },
{ name: 'shubert helmet', price: 20 },
{ name: 'sport gloves', price: 30 }
];
productArray: any = [];
add(product) {
this.productArray.push(product);
}
In your template, you have to change (click)="add()" to (click)="add(product)"

Adjust HTML table with content want to displayed, Angular

My page is about showing data table from user on shift indicator.
My dashboard.component.html
<table class="table">
<thead>
<tr>
<th *ngFor="let col of tablePresetColumns">
{{col.content}}
</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of tablePresetData ">
<td *ngFor="let cell of row"> {{cell.content}}</td>
<td *ngFor="let cell of row">
<span class ="dot" [ngClass]="{
'dot-yellow' : cell.content == 'Busy',
'dot-green' : cell.content == 'Idle',
'dot-red' : cell.content == 'Overload'}">
</span>
</td>
</tr>
</tbody>
</table>
My example data :
tablePresetColumns = [{ id: 1, content: "Username" }];
tablePresetData = [
[{ id: 1, content: "Adiet Adiet" }, { id: 2, content: "Idle" }],
[{ id: 1, content: "Andri Irawan" }, { id: 2, content: "Idle" }],
[{ id: 1, content: "Ari Prabudi" }, { id: 2, content: "Idle" }]
];
How should i do to :
removes the status in the page that I want to display, so it just
appear username and color indicator
I've tried to change *ngFor into this (with index 1) :
<td *ngFor="let cell of row"> {{cell.content[1]}}
but it didn't works at all
Try
<td> {{row[0].content}}</td>
instead of
<td *ngFor="let cell of row"> {{cell.content[1]}}
How about this
<table class="table">
<thead>
<tr>
<th *ngFor="let col of tablePresetColumns">{{col.content}}</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of tablePresetData">
<ng-container *ngFor="let cell of row, let i = index">
<td *ngIf="i == 0">{{cell.content}}</td>
<td *ngIf="i == 0">
<span
[ngClass]="{
'dot-yellow' : row[1].content == 'Busy',
'dot-green' : row[1].content == 'Idle',
'dot-red' : row[1].content == 'Overload'}"
>
</span>
</td>
</ng-container>
</tr>
</tbody>
</table>
See here for a live example: https://codesandbox.io/s/7y2r69992j
Note
I think your data structure is a but awkward and un-semantic. It would be better, if your data would look like this:
tablePresetColumns = ["Username", "Status"];
tablePresetData = [
{username: "Adiet Adiet", status: "Idle"},
{username: "Andri Irawan", status: "Busy" },
{username: "Ari Prabudi", status: "Overload" }
];
So you could show the table like this
<table class="table">
<thead>
<tr>
<th *ngFor="let col of tablePresetColumns">{{col}}</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of tablePresetData">
<td>{{ row.username }}</td>
<td>
<span [ngClass]="{
'dot-yellow' : row.status == 'Busy',
'dot-green' : row.status == 'Idle',
'dot-red' : row.status == 'Overload'
}">
</span>
</td>
</tr>
</tbody>
</table>
Much easier to read and maintain.
Also a live example: https://codesandbox.io/s/o27pv052z
You need to use .map on tablePresetData and have some changes on object structure
angular code here:
tablePresetColumns: any = [
{thTitle:"id", thWidth:'30px'},
{thTitle:"Username", thWidth:'160px'},
{thTitle:"Status", thWidth:'100px'},
{thTitle:"", thWidth:'60px'}
];
tablePresetData: any = [
{ id: 1, Username: "Adiet Adiet", status: "Idle" },
{ id: 2, Username: "Andri Irawan", status: "Overload" },
{ id: 3, Username: "Ari Prabudi", status: "Busy" }
];
constructor() {}
ngOnInit() {
this.tablePresetData.map((item: any) => {
if (item.status === "Busy") {
item["className"] = "dot-yellow";
}
if (item.status === "Idle") {
item["className"] = "dot-green";
}
if (item.status === "Overload") {
item["className"] = "dot-red";
}
});
console.log("this.tablePresetData", this.tablePresetData);
}
Html code
<table>
<thead>
<tr>
<th
*ngFor="let tableHd of tablePresetColumns"
[width]="tableHd.thWidth" >
{{tableHd.thTitle}}
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let tableCol of tablePresetData">
<td>{{tableCol.id}}</td>
<td>{{tableCol.Username}}</td>
<td>{{tableCol.status}}</td>
<td>
<span [ngClass]='tableCol.className' class="circle"></span>
</td>
</tr>
</tbody>
</table>
CSS Class -
.circle{border-radius: 10px; display: inline-block; height: 10px; width: 10px; }
.dot-yellow{background-color: yellow;}
.dot-green{background-color:green;}
.dot-red{background-color:red;}

Edit object of an array using Vue.JS

I am developing my first app using Vuejs + Laravel and I am facing a problem that I couldn't solve until now!
I have an array of object and I need to edit a single of then without delete and add a new one! I have made a JS Bin to show what I need!
JS Bin
When you click in EDIT and start to typing your new value the original value edits as well but I need to change the original value only after the user hit the save button!
Anybody can help me?
PS: I will update my database and then show the new value on the table!
Is there anyway to duplicate my record as I do on the edit function without sync then?
JS
new Vue({
el: 'body',
data: {
cache: {},
record: {},
list: [
{ name: 'Google', id: 1 },
{ name: 'Facebook', id: 2 },
],
},
methods: {
doEdit: function (record) {
this.cache = record;
},
edit: function (record) {
this.record = _.cloneDeep(record);
this.cache = record;
}
}
});
HTML
<div class="container">
<form class="form-horizontal" #submit.prevent="doEdit(record)">
<div class="row">
<div class="col-md-12">
<label>Name</label>
<input type="text" class="form-control" v-el:record-name v-model="record.name">
</div>
<div class="col-xs-12" style="margin-top:15px">
<button type="submit" class="col-xs-12 btn btn-success">Save</button>
</div>
</div>
</form>
<hr>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="r in list">
<td class="text-center" style="width:90px"> {{ r.id }} </td>
<td> {{ r.name }} </td>
<td class="text-center" style="width:90px">
<span class="btn btn-warning btn-xs" #click="edit(r)"><i class="fa-fw fa fa-pencil"></i></span>
</td>
</tr>
</tbody>
</table>
</div>
You can replace the old object with the cloned-updated one.
doEdit: function (record) {
var index = _.indexOf(this.list, this.cache);
this.list.splice(index, 1, record);
}
https://jsbin.com/ruroqu/3/edit?html,js,output
If you want to save the value only after user submitted, you should not bind the record directly such as v-model="record.name".
And we can use Vue.set to change attributes of the original record.
Let's try: JS Bin

Differentiating current textbox value from old one and showing in Angular JS

My code is like this
<body>
<div>
<table ng-app='myApp' ng-controller="MainCtrl">
<thead></thead>
<tbody ng-repeat="prdElement in palletElement track by $index">
<tr>
<td>{{prdElement.name}}</td>
</tr>
<tr ng-repeat="data in prdElement.Data">
<td>{{data.itemId}}</td>
<td>{{data.shipmentId}}</td>
<td>{{data.itemCode}}</td>
<td>{{data.description}}</td>
<td>{{data.handlingUnit}}</td>
<td>{{data.weight}}</td>
<td>{{data.class}}</td>
<td>{{data.lenght}}</td>
<td>{{data.width}}</td>
<td>{{data.height}}</td>
<td>{{data.flag}}</td>
<td>
<input type="text" ng-model="data.quantity" placeholder=" Code" required />
</td>
</tr>
<tr>
<td>
<button ng-click="newPalletItem( prdElement,$event)">Submit</button>
</td>
</tr>
<!--<tr id="displayitems" >
<td>
{{palletElement}}
</td>
</tr>-->
</tbody>
</table>
</div>
(function () {
angular.module('myApp', []).controller('MainCtrl', function ($scope) {
var counter = 0;
$scope.palletElement = [{
name: 'Pallet 1',
Data: [{
name: 'item 1',
itemId: '284307',
shipmentId: 'eb44f690-c97a-40e3-be2a-0449559e171a',
itemCode: '',
description: 'Bicycle parts - frame',
quantity: '31',
handlingUnit: 'CTN',
weight: '613.04',
class: '',
lenght: '102',
width: '42',
height: '61',
flag: 'P'
}, {
name: 'item 2',
itemId: '284308',
shipmentId: 'eb44f690-c97a-40e3-be2a-0449559e171a',
itemCode: '',
description: 'Bicycle parts - fork',
quantity: '22',
handlingUnit: 'CTN',
weight: '242.99',
class: '',
lenght: '75',
width: '34',
height: '18',
flag: 'P'
}]
}]
$scope.newPalletItem = function (palletElement, $event) {
counter++;
$scope.palletElement.push(palletElement);
}
});
}());
When some one changes the value in last column textbox and press submit button I want to calculate [preloded value in textbox - (minus) current value in that text box ] and show it in next row. So far I have managed to duplicate the entire data completely to next row. but have no Idea in how to achieve rest. Can any one pint out a solution.
Fiddle
More details from Fiddle: as you can see current value is first text box is 31 if some one changes it to 10 when I duplicate the row to bottom I want that new textbox value to be shown as 21 (which is 31-10).
Please see here: http://jsfiddle.net/8r8cxcup/
newPalletImte:
$scope.newPalletItem = function (palletElement, $event) {
var npalletElement = {};
angular.copy(palletElement, npalletElement);
counter++;
angular.forEach(npalletElement.Data, function (row) {
if (row.quantity != row.newquantity) {
row.quantity = row.quantity - row.newquantity;
}
});
$scope.palletElement.push(npalletElement);
};
});
HTML:
<table ng-app='myApp' ng-controller="MainCtrl">
<thead></thead>
<tbody ng-repeat="prdElement in palletElement track by $index">
<tr>
<td>{{prdElement.name}}</td>
</tr>
<tr ng-repeat="data in prdElement.Data" ng-init="data.newquantity = data.quantity">
<td>{{data.itemId}}</td>
<td>{{data.shipmentId}}</td>
<td>{{data.itemCode}}</td>
<td>{{data.description}}</td>
<td>{{data.handlingUnit}}</td>
<td>{{data.weight}}</td>
<td>{{data.class}}</td>
<td>{{data.lenght}}</td>
<td>{{data.width}}</td>
<td>{{data.height}}</td>
<td>{{data.flag}}</td>
<td>
<input type="text" ng-model="data.newquantity" placeholder=" Code" required />
</td>
</tr>
<tr>
<td>
<button ng-click="newPalletItem( prdElement,$event)">Submit</button>
</td>
</tr>
<!--<tr id="displayitems">
<td>
{{palletElement}}
</td>
</tr>-->
</tbody>
</table>

Categories

Resources