I have an e-commerce page. I want when the user deletes a product from the shopping cart to reload the specific divs. I have the index page that contains
a div with an ng-repeat with my products, and in the index I have an content view with the same ng-repeat. I want when for example I delete a
product, to update the these ng-repeat. I tried, the $rootscope.$digest; and $scope.$apply(); but there are not working. Below, you can see my code.
My index page
<div ng-controller="ShoppingCartCtrl">
<div data-toggle="dropdown"> </div>
<ul>
<li ng-repeat="item in resultShoppingCart">
<a title="Product Title Here" ui-sref="single_product({id:item.productId})"></a>
<div class="product-details">
<div class="access"><a title="Remove This Item" ng-click="delete(userId,item.productId)">Remove</a> <a class="btn-edit" title="Edit item" ui-sref="shoppingCart"><i class="icon-pencil"></i><span class="hidden">Edit item</span></a> </div>
<p class="product-name"><a ui-sref="single_product({id:item.productId})" ng-bind="item.productName"></a> </p>
<strong ng-bind="item.quantity"></strong> x <span class="price" ng-bind="item.unitPrice"></span>
</div>
</div>
</li>
</ul>
</div>
</div>
<div class="actions">
<a ui-sref="shoppingCart"><span>View Cart</span></a>
</div>
<div id="wrap">
<!-- Content -->
<div class="container">
<div ui-view=""></div>
</div>
</div>
My shopping cart page
<tbody>
<tr ng-repeat="item in resultShoppingCart track by $index">
<td class="cart_product"><a ui-sref="single_product({id:item.productId})"></a></td>
<td class="cart_description">
<p class="product-name" ng-bind="item.productName"></p>
</td>
<td class="price" ng-bind="item.unitPrice"><span></span></td>
<td class="qty">
<input class="form-control input-sm" type="text" ng-value="item.quantity" ng-model="item.quantity">
<i class="fa fa-plus" ng-click="changeQuantity(item, 1)"></i> <i class="fa fa-minus" ng-click="changeQuantity(item, -1)"></i>
</td>
<td class="price" ng-bind="item.price"><span></span></td>
<td class="action"><a ng-click="delete(userId,item.productId)">Delete item</a></td>
</tr>
</tbody>
And my shopping cart controller:
$scope.delete = function (userId, productId) {
var jsonDelete = '...';
dataProvider.delete(jsonDelete).then(function (response) {
//$scope.$digest(); //not working
//$scope.$apply();//not working
});
$state.reload();
//$scope.$digest;//not working
//$scope.$apply();//not working
};
With the state.reload I can reload my shopping cart page. Can anyone help me?
Few modifications will make it work.
Pass $index to your delete function, like,
ng-click="delete(userId,item.productId, $index)"
Then inside your delete handler, you can use splice to delete the object from your existing array. Like
$scope.delete = function (userId, productId, index) {
var jsonDelete = '...';
dataProvider.delete(jsonDelete).then(function (response) {
$scope.resultShoppingCart.splice(index, 1);
});
$state.reload();
};
Edit:
Use events to update the parent value. Like,
In shopping cart
$scope.delete = function (userId, productId, index) {
var jsonDelete = '...';
dataProvider.delete(jsonDelete).then(function (response) {
$scope.resultShoppingCart.splice(index, 1);
$rootScope.$emit('updateList',productId);//Passing productid instead of index is safer as it is not necessary to stick to the order of array.
});
$state.reload();
};
In index page
Catch the event which is triggered after deleting.
$rootScope.$on('updateList', function (productId) {
for (let i = 0; i < $scope.resultShoppingCart.length ; i++) {
if ($scope.resultShoppingCart[i].productId == productId) {
$scope.resultShoppingCart.splice(i, 1);
break;
}
}
});
Related
Hello i am new in vuejs and vuetify, i am now want to display item about 400colums and 6 rows, colum_id (cid) and row_id(rid) but render speed is slow sorry may i know how to improve this loop performance Thank before hand :
<v-layout>
<div class="reglahan-table-result-betting">
<tr
v-for="i in 6"
:key="i">
<td
v-for="j in 60"
:key="j">
<div
v-for="(item, k) in props.resultBetting"
:key="k">
<span
v-if="Number(item.cid) === j && Number(item.rid) === i"
:class="item.color"
/>
</div>
<span class="no-circle" />
</td>
</tr>
</div>
</v-layout>
Of course you can optimize that. The problem is that in your most inner loop, you loop on every element of the array. You shouldn't do that.
First you need to properly index your table, I would create a 'computed' function as such :
computed: {
indexedResultBetting: function () {
let ret = {}
self.props.resultBetting.forEach(function(item, index){
if(!item.rid in ret)
ret[item.rid] = {}
ret[item.rid][item.cid] = item.color
})
return ret
}
}
Then you can simply show that with something like :
<v-layout>
<div class="reglahan-table-result-betting">
<tr
v-for="i in Object.keys(indexedResultBetting)"
:key="i">
<td
v-for="j in Object.keys(indexedResultBetting[i])"
:key="j">
<div
<span
:class="indexedResultBetting[i][j]"
/>
</div>
<span class="no-circle" />
</td>
</tr>
</div>
</v-layout>
I haven't tested it, there is certainly some tinkering to do.
I am trying to show items into shopping cart when i click add to card button but i am facing some errors How to fit it error
Please see error
Non-static method Gloudemans\Shoppingcart\Cart::add() should not be called statically
https://flareapp.io/share/Bm06697x
Controller
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Gloudemans\Shoppingcart\Cart;
class CartController extends Controller
{
public function cart()
{
return view('front_end/cart');
}
public function addcart(Request $request){
$image = [$request->product_image];
$add=Cart::add(
$request->productid,
$request->product_name,
$request->qty,
$request->product_price,
$image
);
return redirect()->route('cart.index')->with('success_message', 'Item was added to your cart!');
}
}
html view
<tbody class="cart-table__body">
#foreach(Cart::content() as $items)
<tr class="cart-table__row">
<td class="cart-table__column cart-table__column--image">
<img src="{{$items->product_image}}" alt="">
</td>
<td class="cart-table__column cart-table__column--product">
{{$items->product_name}}
</td>
<td class="cart-table__column cart-table__column--price" data-title="Price">{{$items-
>product_price}}</td>
<td class="cart-table__column cart-table__column--quantity" data-title="Quantity">
<div class="input-number">
<input class="form-control input-number__input" type="number" min="1" value="{{$items->qty}}">
<div class="input-number__add"></div>
<div class="input-number__sub"></div>
</div>
</td>
<td class="cart-table__column cart-table__column--total" data-title="Total"></td>
<td class="cart-table__column cart-table__column--remove">
<a href="" class="btn btn-light btn-sm btn-svg-icon">
<svg width="12px" height="12px">
<use xlink:href="{{url('public/assets/images/sprite.svg#cross-12')}}"></use>
</svg>
</a>
</td>
</tr>
#endforeach
</tbody>
Use this in your controller and pass data your in view
$cart_list = Cart::content();
$cart_data = [];
foreach($cart_list as $cart){
$cart_data [] = [
//define keys as per your cart's content and pass $cart_data in your view
];
}
}
EDIT:
Sorry i was reading the question wrong.
Where is defined your function add() just add static
public static function add() {
//.....
}
or
static public function add() {
// ......
}
OLD POST
I don't see, where u're defining which cart is for which user, but I would do it in this way.
Controller
$userId = Auth::id(); // Get the ID from Session of a logged user.
$carts = Cart::where('user_id', $userId)->get(); // Get all products linked to user
return view('cart')->withCarts($carts); // Return the view with data
Blade
#foreach($carts as $cart) // U foreach every product linked to user
{{ $cart->product_name }}
{{ $cart->product_price}}
{{ $cart->product_image }}
#endforeach
If the user is not logged in, you can create a cart with the cookie id on youtube are hundreds of tutorials how to make an e-commerce cart.
Hope this helps
i'm iterating through map where key and value pair is there and i'm not getting how to apply pagination of those data where that map data is generated from the database directly.i'm iterating through map where key and value pair is there and i'm not getting how to apply pagination of those data where that map data is generated from the database directly.
<table>
<thead></thead>
<tbody>
<tr>
<td><marquee>
<h3>
A tag is a keyword or label that categorizes your question with
other, similar questions. Using the right tags makes it easier
for others to find and answer your question.
</h4>
</marquee>
<hr></td>
</tr>
<tr ng-repeat="(key,value) in tagForm.data track by $index">
<td align="left">
<div ng-init='tagForm.getTag(key)'
class=" w3-container w3-card w3-white w3-margin w3-round "
style="padding-left: 40px; padding-right: 40px;">
<br>
<p ng-repeat="data2 in tagForm.message track by $index">
<a ng-click="tagForm.getAnswer(key)">Q. {{value}}</a> <span
class="badge">{{data2}}</span> <br>
</p>
<ul ng-repeat="(key2,value2) in tagForm.ans track by $index">
<li><b ng-if="key==key2">Ans. {{value2}}</b></li>
</ul>
<div ng-init='tagForm.getUser(key)'>
<b>Posted
by:{{tagForm.user2[$index]}}</b>
</div>
<button class="btn btn-default" id="{{$index}}"
ng-click="count1=count1+1" ng-init="count1=5+($index*3)-5">
Upvote <span class="badge">{{count1}}</span>
</button>
<button class="btn btn-default" id="{{$index}}"
ng-click="count=count+1" ng-init="count=1+($index*2)">
Downvote<span class="badge">{{count}}</span>
</button>
<button class="btn btn-default" ng-click="gotoanswer()">Answer
this question</button>
<br> <br />
</div> <br>
</td>
<td height=100px><br /></td>
</tr>
</tbody>
</table>
use the following pagination in your html file
<uib-pagination ng-show="isPaginate == false "
total-items="totalItems" ng-model="currentPage"
boundary-links="true" items-per-page="numPerPage"
class="pagination-sm" ng-change="pageChanged()" max-size="5">
</uib-pagination>
and then initialize the variable as per requirement in angular controller
$scope.totalItems = 80;//length of records
$scope.currentPage = 1;
$scope.numPerPage = 10;
var startpos = 0;
for dynamically loading records (loading records batch wise instead of loading all at time) refer following function
$scope.pageChanged = function() {
// if($scope.currentPage!=1)
$scope.isCollapsed = false;
$scope.isRCollapsed = false;
$scope.page = ($scope.currentPage - 1) * $scope.numPerPage;
callApi($scope.page);//get next set of 10 records
console.log('Page changed to: ' + $scope.currentPage);
};
I have a PrimeNg turbotable with row expansion feature.
How can I expand the rows by default.
Here is my Code :
HTML
<p-table [columns]="cols" [value]="cars" dataKey="vin">
<ng-template pTemplate="header" let-columns>
<tr>
<th style="width: 2.25em"></th>
<th *ngFor="let col of columns">
{{col.header}}
</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-rowData let-expanded="expanded" let-columns="columns">
<tr>
<td>
<a href="#" [pRowToggler]="rowData">
<i [ngClass]="expanded ? 'fa fa-fw fa-chevron-circle-down' : 'fa fa-fw fa-chevron-circle-right'"></i>
</a>
</td>
<td *ngFor="let col of columns">
{{rowData[col.field]}}
</td>
</tr>
</ng-template>
<ng-template pTemplate="rowexpansion" let-rowData let-columns="columns">
<tr>
<td [attr.colspan]="columns.length + 1">
<div class="ui-g ui-fluid" style="font-size:16px;padding:20px">
<div class="ui-g-12 ui-md-3" style="text-align:center">
<img [attr.alt]="rowData.brand" src="assets/showcase/images/demo/car/{{rowData.brand}}.png">
</div>
<div class="ui-g-12 ui-md-9">
<div class="ui-g">
<div class="ui-g-12">
<b>Vin:</b> {{rowData.vin}}
</div>
<div class="ui-g-12">
<b>Vin:</b> {{rowData.color}}
</div>
<div class="ui-g-12">
<b>Brand:</b> {{rowData.brand}}
</div>
<div class="ui-g-12">
<b>Color:</b> {{rowData.color}}
</div>
</div>
</div>
</div>
</td>
</tr>
</ng-template>
</p-table>
Ts
export class TableRowExpansionDemo implements OnInit {
cars: Car[];
cols: any[];
constructor(private carService: CarService) { }
ngOnInit() {
this.carService.getCarsSmall().then(cars => this.cars = cars);
this.cols = [
{ field: 'vin', header: 'Vin' },
{ field: 'year', header: 'Year' },
{ field: 'brand', header: 'Brand' },
{ field: 'color', header: 'Color' }
];
}
}
}
I tried using expandedRowKeys attribute, but it is not working for me.
What am I missing here?
Thanks
Update: For Version >7.x
Setting value to 1 won't work on version 7+ use boolean(true/false)
const thisRef = this;
this.cars.forEach(function(car) {
thisRef.expandedRows[car.vin] = true;
});
Working StackBlitz
For Version <7.x
I tried using expandedRowKeys attribute
Yes you're right. So add [expandedRowKeys]="expandedRows"> to p-table element :
<p-table [columns]="cols" [value]="cars" dataKey="vin" [expandedRowKeys]="expandedRows">
and then, you just need to fill expandedRows object with vin values of the rows you want to expand (because dataKey is vin).
Because you want all rows to be expanded, you can fill it like that :
const thisRef = this;
this.cars.forEach(function(car) {
thisRef.expandedRows[car.vin] = 1;
});
in order to have something like
expandedRows = {"dsad231ff": 1, "gwregre345": 1, ...}
See working Plunker
In the accepted answer, the expandedRows mapping to the turbo table expandedRowKeys is one way i.e. it can set the state of rows at the time of loading only.
If someone want to collapse or expand it after the table is loaded, you can directly edit the 'expandedRowKeys' variable by passing the table reference from the html.
Define Your table with a reference variable #dt
<p-table #dt [columns]="cols" [value]="cars" dataKey="vin">
Edit your table body like this to get a on click function trigger
<ng-template pTemplate="body" let-rowData let-expanded="expanded" let-columns="columns">
<tr>
<td>
<a href="#" [pRowToggler]="rowData">
<i [ngClass]="expanded ? 'fa fa-fw fa-chevron-circle-down' : 'fa fa-fw fa-chevron-circle-right'"></i>
</a>
</td>
<td *ngFor="let col of columns">
<a >
<span (click)="onItemClick(rowData, dt)">
{{rowData[col.field]}}
</span>
</a>
</td>
</tr>
</ng-template>
in your TS file add the function as
onItemClick(rowData:any, dt:any) {
if(dt.expandedRowKeys[rowData._id]){
dt.expandedRowKeys[rowData._id] = 0;
}
else {
dt.expandedRowKeys[rowData._id] = 1;
}
}
This approach gives you more freedom in changing state of table on a trigger of event from outside of table and expanding or collapsing multiple rows at once.
After hitting many solution i tried and found easiest way to resolve
<p-table [columns]="cols" [value]="cars" dataKey="vin" [expandedRowKeys]="expandedRows">
Replace datakey value to your unique id key from list of objects fetched from service or http calls.
<p-table [columns]="cols" [value]="repaymentsList" dataKey="id" expandableRows="true" rowExpandMode="single" [responsive]="true">
My MVVM looks like this:
<script type="text/javascript">
function Company(data) {
this.name = ko.observable(data.name);
this.legal_form = ko.observable(data.legal_form);
this.company_number = ko.observable(data.company_number);
this.type_account = ko.observable(data.type_account);
this.type_supplier = ko.observable(data.type_supplier);
this.type_competitor = ko.observable(data.type_competitor);
this.type_other = ko.observable(data.type_other);
this.children = ko.observableArray(data.child);
}
function CompanyListViewModel() {
// Data
var self = this;
self.companies = ko.observableArray([]);
$.getJSON(Routing.generate('contacts_companies_get_json'), function(allData) {
var mappedCompanies = $.map(allData, function(item) { return new Company(item) });
self.companies(mappedCompanies);
});
}
ko.applyBindings(new CompanyListViewModel());
</script>
My View looks like this:
<tbody data-bind="foreach: companies">
<tr>
<td>
<a href="#" class="title">
<span data-bind="text: name"></span> <span data-bind="text: legal_form"></span>
</a>
</td>
<td data-bind="if:$data.company_number"><span data-bind="text: company_number"></span></td>
<td><span data-bind="if: type_account" ><i class="icon-check"></i></span></td>
<td><span data-bind="if: type_supplier" ><i data-bind="if: type_supplier" class="icon-check"></i></span></td>
<td><span data-bind="if: type_competitor" ><i data-bind="if: type_competitor" class="icon-check"></i></span></td>
<td><span data-bind="if: type_other" ><i data-bind="if: type_other" class="icon-check"></i></span></td>
<td>Details</td>
</tr>
</tbody>
I would like to add hidden <tr> for every child that a parent company has and add a plus sign before the parent to expand the hidden .
The problem is that I can only access the child within the original parent <tr> otherwhise will tell me "children" is not defined.
Any suggestions on how to achieve this?
You can use the foreach without a container element to display the children:
<tbody data-bind="foreach: companies">
<tr>
<!-- company columns -->
</tr>
<!-- ko foreach: children -->
<tr>
<!-- children columns -->
</tr>
<!-- /ko -->
</tody>
And with the help of a new property (like showChildren on the Company) you can do the show hide of the childrens:
Demo JSFiddle.
If you want to display the full hierarcy with the same columns so you want to have to display the children of the child campanies you can achieve with recursive templates.
There were some questions about recursive templates latelly:
Recursive template with knockout js
Working with Knockout 'foreach' looping through multidimensional array