Hello I have a shopping cart which I am able to add products as well as delete products using a api . When deleting an item from cart it has to be deleted using a button click on each item by id, one by one. which is fine for that purpose, but I am trying to do empty all items in cart url from a function not a button which has not worked for me because id will be undefined.
My question is, if this is even possible? I have tried clearing the array of items such as cartItems.length = 0 or cartItems = [] this only empties a copy of the array from my understanding, so therefore the items will still exist in the cart from what I have tried.
I'm reaching out to see if anyone can answer this and point me in the right direction it will be greatly appreciated. I have included a snippet of of html and the cart service for the delete item.
cart service
RemoveProductFromCart(id:number):Observable<void>{
return this.http.delete<CartItem[]>(`${this.cartUrl}/${id}`)
.pipe(catchError(_err => of (null))
);
}
cartitem.ts
handleRemoveFromCart(){
alert("hit remove from cart");
this.cartService.RemoveProductFromCart(this.cartItem.id)
.subscribe(() =>
console.log("Product with Id deleted",
this.cartItem.id),
(err) => console.log(err)
);
}
html for cartitem
<div class="container-md" >
<div>
<img class="img-fluid" [src]="cartItem.imageUrl" style="padding-bottom:5px; padding-top:50px" alt="Cart">
<div class="text-nowrap" style="font-size:13px; width: 400px">{{cartItem.productName}}</div>
{{cartItem?.size}}{{Valuesize}}
<div style="font-size:13px;"><strong>{{ (cartItem.price) | currency}}</strong></div>
<div class=" float-right">
<span><i class="fa-solid fa-trash-can" style="color:#D30169; cursor: pointer;" (click)="handleRemoveFromCart();handleReload()"></i></span>
</div>
</div>
</div>
cart html
<div *ngIf="cartItems.length === 0"class="alert alert-
info">Your Cart is Empty</div>
<div *ngIf="product">
<div>{{product.name}}</div>
<input type="number" [(ngModel)]="product.num"
min="0"/>
</div>
<div *ngFor="let item of cartItems; let i = index">
<app-cart-item [cartItem]="item"></app-cart-item>
</div>
<li class="list-group-item" style="margin-top:30px;">
<strong>Total Items {{itemTotal}}</strong>
</li>
<li class="list-group-item active">
<strong>Total: {{ cartTotal | currency}}</strong>
</li>
<li class="btn btn-primary" style="height: 40px;
width:210px; margin-top:20px; color:ffffff">
<a class="" routerLink="/clothing" style="color:
#ffffff; cursor: pointer;">Continue
Shopping</a>
</li>
<li class= "btn" style="height: 40px; width:210px;
margin-top: 20px; background-color:#D30169">
<a class="" routerLink="/checkout" style="color:
#ffffff">Go To Checkout</a>
</li>
</div>
</div>
</div
Have a look into Rxjs
cart.service.ts
Create a behavior subject of cart items
cartItems$ = new BehaviorSubject<CartItem>([]);
To clear all the items
clearCart() {
this.cartItems$.next([]);
}
To add or remove an item
addToCart(cartItem: CartItem) {
this.cartItems$.next([cartItem, ...this.cartItems.getValue()]);
}
removeFromCart(cartItemId: string) {
this.cartItems$.next([this.cartItems.getValue().filter((cartItem) => cartItem.id !== cartItemId)]);
}
cartItem.ts
To subscribe to cartItems
cartItems:CartItem[] = []
constructor(private cartService: CartService) {
this.cartService.cartItems$.subscribe((v) => (this.cartItems = v));
}
Don't forget to unsubscribe
I'm working on a list of items for my website.
I have a list of 5 items with a 'id'. When you click the button, an overlay must be shown with 2 buttons 'change to background to red' and than 'cancel'.
If you click the cancel, the specific 'div class="item"' with the specific id his background must become red.
But, the problem is I don't know how using jquery/javascript to know which button of the div what pressed (button of item id 1 or 2 or 3..)
And also when you click outside the buttons, the overlay must be removed.
Here's the code
$(document).ready(() => {
$('.options-btn').click(function ()
{
var id = $(this).parent().attr('id'); /* find <div class="item"> */
$('body').append('<div class="overlay"></div>');
var append = `
<div class="item-options-active">
<button class="feed-option-btn-number background-btn" tabindex="0">Background set to RED</button>
<button class="feed-option-btn-number cancel-btn" tabindex="0">Cancel</button>
</div>
`;
$(append).appendTo('.overlay');
});
$(document).click(function (e)
{
if (document.getElementsByClassName("overlay").length == 1)
{
if(document.getElementsByClassName("item-options-active").length == 1)
{
// this condition is not working when you click the specific button
if($(".background-btn").data('clicked'))
{
// how to get <div> of the button which was press to change the background??
$('.item').css('background', 'red');
}
}
}
});
})
body {
background: grey;
}
.item {
background: green;
border: 5px solid purple;
margin: 20px;
}
.item button {
margin-left: 10px;
}
.overlay {
position: fixed;
width: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,.85);
z-index: 10000;
}
<body>
<div class="show-items">
<div class="item" id="1">
<button type="button" class="options-btn">check options</button>
</div>
<div class="item" id="2">
<button type="button" class="options-btn">check options</button>
</div>
<div class="item" id="3">
<button type="button" class="options-btn">check options</button>
</div>
<div class="item" id="4">
<button type="button" class="options-btn">check options</button>
</div>
<div class="item" id="5">
<button type="button" class="options-btn">check options</button>
</div>
</div>
</body>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
If you rewrite the .option-btn click event to something like this and delete the document click event it should work:
$('.options-btn').click(function ()
{
var id = $(this).parent().attr('id'); /* find <div class="item"> */
var button = $(this);
$('body').append('<div class="overlay"></div>');
var append = `
<div class="item-options-active">
<button class="feed-option-btn-number background-btn" tabindex="0">Background set to RED</button>
<button class="feed-option-btn-number cancel-btn" tabindex="0">Cancel</button>
</div>
`;
$(append).appendTo('.overlay');
$('.overlay').on('click', function(){
$(this).remove();
}).find('.cancel-btn').on('click', function(){
$(this).closest('.overlay').remove();
});
$('.overlay').find('.background-btn').on('click', function(){
button.closest('.item').css('background', 'red');
$(this).closest('.overlay').remove();
});
});
Working fiddle: https://jsfiddle.net/qntupzj6/
I have a page, where in the top, there's a question, and below that, there's a list of answers, and you can add new answers too. (image below)
In a format like (name of the user who answered) "válasza: ekkor: (date), which means his answer, at this time.
Below every question there are 3 buttons, + C and -, the ppl who asked the question can accept the answer (+), deny the answer (-) and cancel applying or denying (C).
Problem is, if I press any button for example in any row, the effect only applies to the first one.
Accept -> Green Background, Deny -> red, C -> white
Here's the HTML code:
<div class="container" style="...">
<ul class="list-group">
<li id="colorTarget" class="list-group-item" *ngFor="let comment of actualComments">
<div style="...">
<b>{{comment.iro}}</b> válasza, ekkor: {{comment.mikor}} {{comment.leir}}
</div><br/>
<div class="row" style="width:120px;">
<div style="...">
<button class="btn btn-light" id="buttonTarget1" (click)="acceptAnswer(comment.iro,comment.mikor,comment.leir)">
+
</button>
</div>
<div style="...">
<button class="btn btn-light" id="buttonTarget2" (click)="clearAnswer(comment.iro,comment.mikor,comment.leir)">
C
</button>
</div>
<div style="...">
<button class="btn btn-light" id="buttonTarget3" (click)="denyAnswer(comment.iro,comment.mikor,comment.leir)">
-
</button>
</div>
</div>
</li>
</ul>
</div>
And the TypeScript:
acceptAnswer(iro, mikor, iras) {
var x = this.answerid(iro, mikor, iras);
this.actualComments[x].accepted = 1;
var target = document.getElementById("colorTarget");
target.style.background = 'green';
target.style.color = 'white';
}
Deny and Clear Answer functions are exactly like this, but with red and white color.
If you have any idea..please.
So, in short: unique id to all li and pass this unique id to the functions.
try to use CSS classes on li elements:
<div class="container" style="...">
<ul class="list-group">
<li id="colorTarget"
class="list-group-item {{ statuses[i] }}"
*ngFor="let comment of actualComments; let i = index;">
<div style="...">
<b>{{comment.iro}}</b> válasza, ekkor: {{comment.mikor}} {{comment.leir}}
</div>
<br/>
<div class="row" style="width:120px;">
<div style="...">
<button class="btn btn-light"
id="buttonTarget1"
(click)="statuses[i] = 'accept'; acceptAnswer(comment.iro,comment.mikor,comment.leir)">
+
</button>
</div>
<div style="...">
<button class="btn btn-light"
id="buttonTarget2"
(click)="statuses[i] = 'clear'; clearAnswer(comment.iro,comment.mikor,comment.leir)">
C
</button>
</div>
<div style="...">
<button class="btn btn-light"
id="buttonTarget3"
(click)="statuses[i] = 'deny'; denyAnswer(comment.iro,comment.mikor,comment.leir)">
-
</button>
</div>
</div>
</li>
</ul>
</div>
this way each li element will get CSS class ('accept', 'deny' or 'clear'). I made it inline within each button (click) function, it also could be dome in the TS file.
Now just add some SCSS:
li {
&.accept {
color: white;
background: green;
}
&.deny,
&.clear {
color: white;
background: red;
}
}
or CSS:
li.accept {
color: white;
background: green;
}
li.deny,
li.clear {
color: white;
background: red;
}
If you need to isolate li's selection, you may add its ID to each li, like li#colorTarget
Now, in you TS file you do not need to deal with styling:
acceptAnswer(iro, mikor, iras) {
var x = this.answerid(iro, mikor, iras);
this.actualComments[x].accepted = 1;
}
UPDATE
you wrote:
actualComment.accepted represent the accept/deny/clear colors
if I understand correctly, actualComment.accepted will have an integer representing one of three colors. If this is correct, let's assume 1 is green (accepted), 2 and 3 are red (deny and clear). In this case you could only change li from my original answer to:
<li id="colorTarget"
class="list-group-item"
[class.accept]="comment.accepted === 1"
[class.deny]="comment.accepted === 2"
[class.clear]="comment.accepted === 3"
*ngFor="let comment of actualComments">
or add public statusesMap (or ENUM) to your ts file:
statusesMap = {
1: 'accept',
2: 'deny',
3: 'clear'
}
and in your HTML:
<li id="colorTarget"
class="list-group-item {{ statusesMap[comment.accepted] }}"
*ngFor="let comment of actualComments">
Here is what I came up with.
Updated template. Added a div, and moved the *ngFor to it to allow me to grab the data needed to create the id. The createId function build the id based on values used.
<div class="container">
<ul class="list-group">
<div *ngFor="let comment of actualComments">
<li [id]="createId(comment.iro,comment.mikor,comment.leir)" class="list-group-item">
<div>
<b>{{comment.iro}}</b> válasza, ekkor: {{comment.mikor}} {{comment.leir}}
</div>
<br/>
…
</li>
</div>
</ul>
</div>
Addition to the component to create the id. This is used in the template above.
createId(iro, mikor, leir) {
return `${iro}${mikor}${leir}`;
}
Update to acceptAnswer function to use the new id created using the new createId function.
acceptAnswer(iro, mikor, iras) {
const x = this.answerid(iro, mikor, iras);
this.actualComments[x].accepted = 1;
const target = document.getElementById(this.createId(iro, mikor, iras));
target.style.background = 'green';
target.style.color = 'white';
}
I'm trying to create a Bootstrap multi-column dropdown menu for nav-tabs. With the code below, I can select each tab. When I switch to another tab, I can't go back to the prior tab. It looks like all tabs remain active. How can I fix this?
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<style>
.dropdown-menu.multi-column {
width: 400px;
}
.dropdown-menu.multi-column .dropdown-menu {
display: block !important;
position: static !important;
margin: 0 !important;
border: none !important;
box-shadow: none !important;
min-width:100px;
}
</style>
<ul class="nav nav-tabs" id="myTabs" role="tablist">
<li role="presentation" class="active">Summary Table</li>
<li class="dropdown"> States
<div class="dropdown-menu multi-column">
<div class="row">
<div class="col-md-6">
<ul class="dropdown-menu">
<li>Alabama</li>
<li>Alaska</li>
</ul>
</div>
<div class="col-md-6">
<ul class="dropdown-menu">
<li>Maine</li>
<li>Maryland</li>
</ul>
</div>
</div>
</div>
</li>
</ul>
<div class="tab-content" id="myTabContent" style="color:black">
<div class="tab-pane fade in active" role="tabpanel" id="main" aria-labelledby="main-tab">
<table class="table table-striped table-hover table-bordered table-responsive" id="rates">
<thead>
<tr><th>State</th><th>Tax Rate</th></tr>
</thead>
<tbody>
<tr><td id="AL">Alabama</td><td id="AL_T">6.00%</td></tr>
<tr><td id="AK">Alaska</td><td id="AK_T">2.70%</td></tr>
<tr><td id="ME">Maine</td><td id="ME_T">3.00%</td></tr>
<tr><td id="MD">Maryland</td><td id="MD_T">3.00%</td></tr>
</tbody>
</table><br/>
</div>
<div class="tab-pane fade in" role="tabpanel" id="Alabama" aria-labelledby="Alabama-tab">
<h5><span style="text-decoration: underline;">Alabama </span></h5>
</div>
<div class="tab-pane fade in" role="tabpanel" id="Alaska" aria-labelledby="Alaska-tab">
<h5><span style="text-decoration: underline;">Alaska </span></h5>
</div>
<div class="tab-pane fade in" role="tabpanel" id="Maine" aria-labelledby="Maine-tab">
<h5><span style="text-decoration: underline;">Maine </span></h5>
</div>
<div class="tab-pane fade in" role="tabpanel" id="Maryland" aria-labelledby="Maryland-tab">
<h5><span style="text-decoration: underline;">Maryland </span></h5>
</div>
</div>
Add this to the bottom
<script type="text/javascript">
$(function() {
var active = $('a[data-toggle="tab"]').parents('.active').length;
var tabClicked = false;
// Closes current active tab (toggle and pane):
var close = function() {
$('a[data-toggle="tab"]').parent().removeClass('active');
$('.tab-pane.active').removeClass('active');
active = null;
}
// Closing active tab when clicking on toggle:
$('[data-toggle=tab]').click(function(){
if ($(this).parent().hasClass('active')){
$($(this).attr("href")).toggleClass('active');
active = null;
} else {
tabClicked = true;
active = this;
}
});
// Closing active tab when clicking outside tab context (toggle and pane):
$(document).on('click.bs.tab.data-api', function(event) {
if(active && !tabClicked && !$(event.target).closest('.tab-pane.active').length) {
close();
}
tabClicked = false;
});
// Closing active tab on ESC key release:
$(document).keyup(function(e){
if(active && e.keyCode === 27) { // ESC
close();
}
});
});
</script>
And a button before the last < / div >
Close active tab
I know that is not the best solution, but does the work and with a little bit of patience you can do it better.
The answer by #Filipe Amaral was 95% of what this problem needed. After a couple of modifications, it works like a charm.
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('.dropdown-menu li').click (function(){
$('.dropdown-menu li').removeClass('active')
});
$('#main-tab').click (function(){
$('.dropdown-menu li').removeClass('active')
});
});
$(function() {
var active = $('a[data-toggle="tab"]').parents('.active').length;
var tabClicked = false;
// Closes current active tab (toggle and pane):
var close = function() {
$('a[data-toggle="tab"]').parent().removeClass('active');
$('.tab-pane.active').removeClass('active');
active = null;
}
// Closing active tab when clicking on toggle:
$('[data-toggle=tab]').click(function(){
if ($(this).parent().hasClass('active')){
$($(this).attr("href")).toggleClass('active');
active = null;
} else {
tabClicked = true;
active = this;
}
});
// Closing active tab when clicking outside tab context (toggle and pane):
$(document).on('click.bs.tab.data-api', function(event) {
if(active && !tabClicked && !$(event.target).closest('.tab-pane.active').length) {
close();
}
tabClicked = false;
});
// Closing active tab on ESC key release:
$(document).keyup(function(e){
if(active && e.keyCode === 27) { // ESC
close();
}
});
});
</script>
<style>
.dropdown-menu.multi-column {
width: 400px;
}
.dropdown-menu.multi-column .dropdown-menu {
display: block !important;
position: static !important;
margin: 0 !important;
border: none !important;
box-shadow: none !important;
min-width:100px;
}
</style>
<ul class="nav nav-tabs" id="myTabs" role="tablist">
<li role="presentation" class="active">Summary Table</li>
<li class="dropdown"> States
<div class="dropdown-menu multi-column">
<div class="row">
<div class="col-md-6">
<ul class="dropdown-menu">
<li>Alabama</li>
<li>Alaska</li>
</ul>
</div>
<div class="col-md-6">
<ul class="dropdown-menu">
<li>Maine</li>
<li>Maryland</li>
</ul>
</div>
</div>
</div>
</li>
</ul>
<div class="tab-content" id="myTabContent" style="color:black">
<div class="tab-pane fade in active" role="tabpanel" id="main" aria-labelledby="main-tab">
<table class="table table-striped table-hover table-bordered table-responsive" id="rates">
<thead>
<tr><th>State</th><th>Tax Rate</th></tr>
</thead>
<tbody>
<tr><td id="AL">Alabama</td><td id="AL_T">6.00%</td></tr>
<tr><td id="AK">Alaska</td><td id="AK_T">2.70%</td></tr>
<tr><td id="ME">Maine</td><td id="ME_T">3.00%</td></tr>
<tr><td id="MD">Maryland</td><td id="MD_T">3.00%</td></tr>
</tbody>
</table><br/>
</div>
<div class="tab-pane fade in" role="tabpanel" id="Alabama" aria-labelledby="Alabama-tab">
<h5><span style="text-decoration: underline;">Alabama </span></h5>
</div>
<div class="tab-pane fade in" role="tabpanel" id="Alaska" aria-labelledby="Alaska-tab">
<h5><span style="text-decoration: underline;">Alaska </span></h5>
</div>
<div class="tab-pane fade in" role="tabpanel" id="Maine" aria-labelledby="Maine-tab">
<h5><span style="text-decoration: underline;">Maine </span></h5>
</div>
<div class="tab-pane fade in" role="tabpanel" id="Maryland" aria-labelledby="Maryland-tab">
<h5><span style="text-decoration: underline;">Maryland </span></h5>
</div>
</div>
I have the below div tag which contains a dropdown and a carousel. Whenever I select from the dropdown I call a function in an AngularJS controller which calls golang at the backend using http.golang to generate the data to be displayed in the carousel and sends a response which is displayed in the carousel but creates a page refresh. I just want this div to be loaded again and not the entire page to load. How can I do this using AngularJS?
HTML:
<div class="col-xs-11" style="width:750pt; height:180pt; margin-top:30px; ">
<div class="row " style="margin-left:75pt;">
<div class="dropdown">
<label class="text-center" style="margin-top:10pt;font-size:14pt;"> Deals on</label>
<button data-toggle="dropdown" class=" btn dropdown-toggle dropdown-menu-hover-color text-center" style="padding:0px 0px;background-color:white;" href="#"><label style="font-size:14pt; color: #191970;" >{{currentCategory}}</label> <b class="caret"></b></button>
<ul class="dropdown-menu submenu-hover-color dropdown-menu-scroll" style="margin:0;">
<li>{{page.category_name}}</li>
</ul>
<div style="display: inline;" ng-hide="deals"> <label class="text-center" style="margin-top:10pt;font-size:14pt;color: #191970;;">No deals found, please select a different category. </label></div>
</div>
</div>
<div id ="carousel_category" class="carousel slide " ng-show ="deals">
<div class="carousel-inner text-center" style="margin-left:75px;">
<div class="item active">
<div class="carousel-width" ng-repeat="(key, value) in categoryList.slice(0, 5) track by $index">
<img ng-src= {{value.imageUrl}} alt="No Image"/>
<h6>{{value.productName}}</h6>
<b style="color:#990000;">{{value.price}}</b> <b style="color:green;">{{value.discount}}</b>
</div>
</div>
<div class="item" ng-repeat="page in category_products_pages">
<div class="carousel-width" ng-repeat="image in page">
<img ng-src= {{image.imageUrl}} alt="No Image" />
<h6>{{image.productName}}</h6>
<b style="color:#990000;">{{image.price}}</b> <b style="color:green;">{{image.discount}}</b>
</div>
</div>
</div> <!--End of carousel-inner-->
<a class="left carousel-control pull-left" href="#carousel_category" data-slide="prev"><i class="glyphicon glyphicon-chevron-left"></i></a>
<a class="right carousel-control pull-right" href="#carousel_category" data-slide="next"><i class="glyphicon glyphicon-chevron-right"></i></a>
</div><!--End of carousel_cartegory-->
</div>
Angularjs :(Below code is inside angularjs controller)
$scope.changeCategory = function(category_id) {
$http({
method : 'POST',
url : '/changeCategory',
data : {"category_id" : category_id},
headers : { 'Content-Type': 'application/x-www-form-urlencoded' }
// set the headers so angular passing info as form data (not request payload)
}).success(function(data, status, headers, config) {
$scope.deals = true;
$scope.products = JSON.parse(JSON.stringify(data));
$scope.currentCategory = $scope.products.categoryInfo.category_name;
$scope.dropdownCategoryList = $scope.products.dropdownCategoryList;
$scope.categoryList = $scope.products.categoryList;
if($scope.categoryList == undefined) {
$scope.deals = false;
return;
}
currList = $scope.categoryList;
for(var i=0;i<currList.length;i++){
product_type = currList[i].product_type;
if (product_type != "Price_With_Discount") {
currList[i].price = "";
currList[i].discount = "Save Upto "+currList[i].discount + "%";
} else {
currList[i].price = "$" + currList[i].price;
currList[i].discount = "(Save "+currList[i].discount+"%)"
}
}
//category_data
var category_products_page = [];
var category_products_pages = [];
var count_1 = 5;
$scope.category_products_pages = category_products_pages;
for(var j=5;j<$scope.categoryList.length;j++){
if(count_1 > 1){
category_products_page.push($scope.categoryList[j]);
count_1--;
if($scope.categoryList.length === j+1){
category_products_pages.push(category_products_page);
//return;
break;
}
}else{
category_products_page.push($scope.categoryList[j]);
category_products_pages.push(category_products_page);
category_products_page = [];
count_1 = 5;
}
}
}).error(function(data, status, headers, config) {
$scope.status = status;
$window.alert("error")
});
}
});