Good Day!
I'm working on my project right now and I need to dynamically add form when button click. I have a nested accordion and inside the accordion is ng-select. To make it clear this is my code
<div class="box box-default" *ngFor="let form of forms; let form_array_index = index">
<div class="box-header with-border text-center">
<h3 class="box-title">
<div class="row">
<div class="col-md-4">
<select2 id="segment" name="segment"
[data]="add_segment"
[width]="293"
[value]="segment_value"
(valueChanged)="changedSegment($event, form_array_index)"
required>
</select2>
</div>
</div>
</h3>
<div class="box-tools pull-right">
</div>
</div>
<div class="box-body">
<div class="row">
<div class="col-md-2">
<label for="category">Values:</label>
<select2 id="category" name="category"
[options]="options"
[data]="add_category"
[width]="293"
[value]="category_value"
(valueChanged)="changedCategory($event, form_array_index)"
required>
</select2>
</div>
</div>
<div class="box-header with-border text-center" *ngIf="cat_value">
<div class="panel panel-default">
<div class="panel-heading">
<h5 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion1" href="#{{ category_current[form_array_index] }}">{{collection_category[form_array_index].category}}
</a>
</h5>
</div>
<div id="{{ category_current[form_array_index] }}" class="panel-collapse collapse">
<div class="panel-body">
<div class="panel-body">
<button class="btn btn-success btn-xs pull-left" (click)="addQuestions()">Add Question</button>
<div class="row" >
<select2 *ngIf="query" id="question" name="question"
[data]="add_question"
[width]="293"
[value]="question_value"
(valueChanged)="changedQuestion($event)"
required>
</select2>
</div>
<button class="btn btn-success btn-xs pull-left" (click)="addSubCat()">Add Sub Category</button>
<div class="row" >
<select2 *ngIf="subcat" id="subcategory" name="subcategory"
[options]="options"
[data]="add_subcategory"
[width]="293"
[value]="subcategory_value"
(valueChanged)="changedSubcategory($event, form_array_index)"
required>
</select2>
</div>
<div class="panel-group" id="accordion21" *ngIf="subcat">
<ul class="list-group">
<li class="list-group-item" >
<div class="panel">
<a data-toggle="collapse" data-parent="#accordion21" href="#{{ subcategory_current }}" >
<strong>{{ get_subcategory }} </strong>
</a>
<div id="{{subcategory_current}}" class="panel-collapse collapse">
<div class="panel-body">
<label for="question">Question:</label>
<select2 id="question" name="question"
[data]="add_question"
[width]="293"
[value]="question_value"
(valueChanged)="changedQuestion($event)"
required>
</select2> <br>
</div>
</div>
</div>
</li>
</ul>
</div>
</div>
</div></div>
</div>
<div class="box-tools pull-right">
</div>
</div>
</div>
This means in SEGMENT it can have multiple CATEGORY and inside category it can have a question or they they Choose SUB CATEGORY and they have to choose a question
This is my component.ts
public collection_category = [];
public collection_subcategory = [];
addSegment(){
this._q_service.addSegment().
subscribe(
data => {
this.add_segment = Array.from(data);
let id = 0;
let text = 'Select Segment';
this.add_segment.unshift({id,text});
// this.segment_value = [];
this.segment_current = this.segment_value;
},
err => console.error(err)
);
}
changedSegment(data: any, form_array_index: any) {
this.segment_current = data.value;
if(this.segment_current.length > 0){
for (let i = 0; i < this.add_segment.length; ++i) {
if (this.add_segment[i].id == this.category_current) {
this.collection_category[form_array_index].segment = this.add_segment[i].text;
}
}
}
console.log('segment', this.collection_category);
}
addCategory(){
this._q_service.addCategory().
subscribe(
data => {
this.add_category = Array.from(data);
this.category_value = [];
this.options = {
multiple: true
}
let id = 0;
let text = 'Select Category';
this.add_category.unshift({id,text});
this.category_value = [];
// this.category_current.push(this.category_value);
// console.log(this.category_current);
},
err => console.error(err)
);
}
changedCategory(data: any, form_array_index: any ) {
this.category_current = data.value;
if(this.category_current.length > 0){
let len = this.add_category.length;
for (let i = 0; i < len; ++i) {
if (this.add_category[i].id == this.category_current) {
this.get_category = this.add_category[i].text;
this.collection_category[form_array_index].category = this.add_category[i].text;
}
}
this.cat_value = true;
}
console.log(this.collection_category);
this.addSubCategory();
this.addQuestion();
}
addSubCategory(){
this._q_service.addSubCategory().
subscribe(
data => {
this.add_subcategory = Array.from(data);
this.subcategory_value = [];
this.options = {
multiple: true
}
let id = 0;
let text = 'Select Sub Category';
this.add_subcategory.unshift({id,text});
this.subcategory_value = [];
this.subcategory_current = this.subcategory_value;
},
err => console.error(err)
);
}
changedSubcategory( data: any, form_array_index: any ) {
this.subcategory_current = data.value;
if(this.subcategory_current.length > 0){
let len = this.add_subcategory.length;
for (let i = 0; i < len; ++i) {
if (this.add_subcategory[i].id == this.subcategory_current) {
this.get_subcategory = this.add_subcategory[i].text;
this.collection_category[form_array_index].subcategory = this.add_subcategory[i].text;
// this.collection_subcategory[form_array_index].subcategory_collection = [];
}
}
this.sub_value = true;
}
}
addQuestion(){
this._q_service.questionList().
subscribe(
data => {
this.add_question = Array.from(data);
this.question_value = [];
let id = 0;
let text = 'Select Question';
this.add_question.unshift({id,text});
this.subcategory_value = ['0'];
this.question_current = this.question_value;
},
err => console.error(err)
);
}
changedQuestion(data: any) {
this.question_current = data.value;
if(this.question_current != 0){
let len = this.add_question.length;
for (let i = 0; i < len; ++i) {
if (this.add_question[i].id == this.question_current) {
this.get_question = this.add_question[i].text;
}
}
}
}
addFormRow(){
let new_form ={
id: '',
segment: '',
category: '',
subcategory: '',
question: ''
};
// this.category_current.push(0);
let segment_categories = {
segment: '',
category: '',
subcategory: '',
question: ''
};
//this.category_current[form_array_index].category
this.collection_category.push(segment_categories);
this.forms.push(new_form);
}
*And every time the user hit the Add Form button it dynamically add form *
But it gives me an error every time I add form the first accordion is not working on the second form but the first form is working well
Related
How to create a onclick event for each search results items so that it render a product page with meta data of that item. I have successfully able to filter items as per keypress. Now I want to give a click event for filtered item to open a product page. How would I do that in Javascript? Please help me figure out this.
**My HTML code**
<!-- Search form -->
<div class="container">
<div class="active-pink-4 mb-4 mt-4">
<input class="form-control form_search" type="text" placeholder="Search" aria-label="Search" id="search">
</div>
<div id="match-list" name="matchid"></div>
</div><!-- End of Search form -->
<div class="container"><!-- Strat of login container-->
<div class="row" id="viewhide"><!-- Strat of login row-->
<div class="col-md-6 d-none d-sm-block"><!--start of col login img-->
<img src="https://img.etimg.com/thumb/width-1200,height-900,imgsize-27424,resizemode-1,msid-14351710/industry/healthcare/biotech/pharmaceuticals/free-medicines-to-all-patients-in-government-hospitals-from-november.jpg">
</div><!--End of col login img-->
<div class="col-md-6 text-center fadeIn first"><!--Start col login-->
<h2>Sign In</h2>
<!-- Login Form -->
<form>
<input type="text" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Username">
<input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password">
<div id="formFooter">
<a class="underlineHover mb-2" href="#">Forgot Password?</a>
</div>
<input type="submit" class="btn btn-primary d-flex justify-content-center d-md-table mx-auto mb-2 btn-round" value="Login">
<h5>You don't have an account ?</h5>
<input type="button" class="btn btn-primary d-flex justify-content-center d-md-table mx-auto mb-5 btn-round" value="Register">
</form>
</div><!-- End of col login-->
</div><!-- End of login row-->
</div><!-- End of login container-->
**My Js code:**
const search = document.getElementById('search');
const matchList = document.getElementById('match-list');
// Search states.json and filter it
const searchStates = async searchText =>{
const res = await fetch('lib/json/data.json').then(response =>{
//console.log(response);
if (!response.ok) {
throw Error("Error");
}
return response.json();
}).then(data =>{
//console.log(data.item);
let states = data.item;
//console.log(states, "states");
// Get matches to current text input
let matches = states.filter(state =>{
const regex = new RegExp(`^${searchText}`, `gi`);
return state.itemName.match(regex) || state.itemMfrCode.match(regex);
});
let divhide = document.getElementById('viewhide');
if(searchText.length !== 0){
divhide.style.display = "none";
}else{
divhide.style.display = "flex";
}
//Hide all results when input is empty
if (searchText.length === 0) {
matches = [];
matchList.innerHTML = '';
}
//Hide if no results are found
if (searchText !== states) {
match = [];
matchList.innerHTML = '';
}
outputHtml(matches);
}).catch(error =>{
console.log(error);
});
};
//Show results in HTML
const outputHtml = matches => {
if (matches.length > 0) {
const html = matches.map(match => `
<div class="card card-body mb-1" id="medprod" name="selectid"
onclick="getproduct()">
<h4 style="cursor: pointer;">${match.itemName}</h4>
</div>
`).join('');
matchList.innerHTML = html;
}
}
search.addEventListener('input', () => searchStates(search.value));
//On clcik search result items function
function getproduct(){
}
**My Json structure**
{
"clientId": "1234",
"systemId": "2010",
"orderReferenceNo": "43442",
"responseCode": "0000",
"responseDescription": "Items successfully retrieved!",
"item": [
{
"itemMfrCode": "0001001",
"qnty": "00000000",
"itemName": "clinic shampoo",
"unitPk": "30ml",
"itemCategory": " ",
"itemType": "NT",
"schemeRange": "000",
"schemeOffeQty": "000",
"rateDiffFlag": "N",
"schemeHalfValueFlag": " ",
"schemeHalfValuePerc": null,
"ratePerUnit": 20.00
},
{},
}
I should have posted the answer long before. No problem, hope it helps someone in future.
const search = document.getElementById('search');
const matchList = document.getElementById('match-list');
const productLayout = document.getElementById('product_layout');
//Search filter
const searchStates = async searchText => {
const res = await
fetch('https://data.json').then(response => {
if (!response.ok) {
throw Error("Error");
}
return response.json();
}).then(data => {
console.log(data.item);
let states = data.item;
console.log(states, "states");
matchList.style.display = 'block';
// Get matches to current text input
let matches = states.filter(state => {
const regex = new RegExp(`^${searchText}`, `gi`);
return state.itemName.match(regex) ||
state.itemMfrCode.match(regex);
});
if (searchText.length !== 0) {
productLayout.style.display = 'none';
} else {
productLayout.style.display = 'block';
}
outputHtml(matches);
}).catch(error => {
console.log(error);
});
};
//Show results in HTML
const outputHtml = matches => {
if (matches.length > 0) {
//Meta data of clicked item
//Keep adding
//${match.itemId},${match.itemRate},${match.itemColor} to the list.
const html = matches.map(match => `
<li id="${match.itemMfrCode}">${match.itemName}</li>
`).join('');
matchList.innerHTML = html;
}
}
search.addEventListener('input', () => searchStates(search.value));
/*OnClick filtered items*/
matchList.addEventListener('click', function(e) {
var target = e.target;
while (target && target.parentNode !== matchList) {
target = target.parentNode;
if (!target) {
return;
}
}
if (e.target.tagName === 'LI') {
//Get selected product name
let liInnerText = e.target.innerText;
//Store prod name in localStorage
localStorage.setItem('liText', liInnerText);
//Insert selected item in input text field
search.value = liInnerText;
//Hide search dropdown after click event
matchList.style.display = 'none';
/*View product layout*/
productLayout.style.display = 'block';
//Get product name from localStorage
var selectedName = localStorage.getItem('liText');
//Dispaly product name in HTML page
document.getElementById('prod_name').innerHTML =
selectedName;
}
});
#match-list {
display: none;
}
#product_layout {
display: none;
}
<!-- Search form -->
<div class="container" id="search_layout">
<div class="active-pink-4 mb-2 mt-4">
<input class="form-control form_search" type="text" placeholder="Search" aria-label="Search" id="search" value="" autocomplete="off" onfocus="this.value=''">
</div>
<ul id="match-list" name="matchid"></ul>
</div>
<!-- End of Search form -->
<!--Product details-->
<div class="container-fluid" id="product_layout">
<div>
<p id="prod_name"></p>
</div>
I'm a new mvc developper, I make a list in my controller, my view show this list and for each row i have a button for a modal view.I want to pass the data of the ViewBag in my list according for each row in my modal.
This is my modal html:
<div class="modal" id="addBadgetoStudentModal-#item.ID" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg animated bounceInDown">
<div class="modal-content">
#using (Html.BeginForm("AddBadgeToStudent", "Badges", new { ID = item.ID }, FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="modal-header">
<h4 class="modal-title">Badges</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
</div>
<div class="modal-body">
<div class="form-group">
<div class="">
<div class="row">
#if (ViewBag.Badges != null)
{
for (var i = 0; i < ViewBag.Badges.Count; i++)
{
<div class="col-lg-3 col-sm-6 col-md-4">
<div class="team-member ">
<div class="row margin-0">
<div class="team-info" style="text-align:center; border: 1.2pt solid #1874BF;">
<img src="#ViewBag.Badges[i].ImageURL" style="width:80%;" class="img-fluid" />
</div>
<div class="team-info" style="text-align:center; width:100%;">
#ViewBag.Badges[i].Label
<br />
<input id="Badge_#ViewBag.Badges[i].ID" class="checkBoxBadgeClass" type="checkbox" />
</div>
</div>
</div>
</div>
}
}
</div>
</div>
</div>
</div>
<div class="modal-footer">
<i class="fa fa-plus-circle"></i> #Resource.Add
</div>
}
</div>
</div>
</div>
<a class="fa fa-pencil-alt" data-toggle="modal" href="#addBadgetoStudentModal-#item.ID" onclick="btnModal()"></a>
This is my List Html View:
#foreach (var item in Model)
{
<tr id="#item.ID">
<td style="text-align:center; width:5%;">
#Html.DisplayFor(modelItem => item.ID)
</td>
<td style="text-align: center; width:25%;">
#item.FullName
</td>
<td style="width:450px;">
#for (var i = 0; i < item.BadgesAssigned.Count; i++)
{
<img src="#item.BadgesAssigned[i].ImageUrl" width="50" title="#item.BadgesAssigned[i].Name" style="float:left;" />
}
<input type="hidden" id="studentBadges_#item.ID" value="#String.Join(",", item.BadgesAssigned.Select(x => x.ID.ToString()))"/>
</td>
}
and this my controller to get my student list and in another table get the badge assigned to a student, so in the list view the student can have 20 badges/25:
public ActionResult BadgeManagement(int? CohortId, int? id)
{
ViewBag.CohortId = db.Cohorts.Select(p => new SelectListItem
{
Text = p.Name,
Value = p.ID.ToString()
});
if (CohortId != null ? CohortId > 0 : false)
{
var cs = db.CohortSubscriptions.Where(student => student.CohortId == CohortId).Include(c => c.Cohorts).Include(c => c.Registrations);
List<BadgesByStudentViewModel> badgesByStudentList = new List<BadgesByStudentViewModel>();
foreach (var student in cs) {
badgesByStudentList.Add(new BadgesByStudentViewModel
{
ID = student.ID,
FullName = student.Registrations.FullName,
BadgesAssigned = db.Enrolled_Students_Badges.Where(x => x.CohortSubscriptionId == student.ID).Select(x => new BadgesAssigned
{
ID = x.ID,
Name = x.Label,
ImageUrl = x.ImageURL
}).ToList()
});
}
ViewBag.Badges = db.Badges.ToList();
return View(badgesByStudentList.ToList());
}
return View(new List<BadgesByStudentViewModel>());
}
I found my solution
This is my html:
<tbody>
#foreach (var item in Model)
{
<tr id="#item.ID">
<td style="text-align:center; width:5%;">
#Html.DisplayFor(modelItem => item.ID)
</td>
<td style="text-align: center; width:25%;">
#item.FullName
</td>
<td style="width:450px;">
#for (var i = 0; i < item.BadgesAssigned.Count; i++)
{
<img src="#item.BadgesAssigned[i].ImageUrl" width="50" title="#item.BadgesAssigned[i].Name" style="float:left;" />
}
</td>
<td style="text-align:center; width:5%;">
<button style="border:none;background: transparent;" data-studentid="#item.ID" data-studentname="#item.FullName" data-badges="#String.Join(",", item.BadgesAssigned.Select(x => x.ID.ToString()))" data-toggle="modal" data-target="#addBadgetoStudentModal" class="modalLink"><i class="fa fa-pencil-alt"></i></button>
</td>
</tr>
}
</tbody>
</table>
<div class="modal" id="addBadgetoStudentModal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg animated bounceInDown">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Badges</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
</div>
<div class="modal-body">
<div class="form-group">
<div class="">
<u>#Resource.AddBadgeToStudent:</u>
<br />
<br />
<div class="row">
#if (ViewBag.Badges != null)
{
for (var i = 0; i < ViewBag.Badges.Count; i++)
{
<div class="col-lg-3 col-sm-6 col-md-4">
<div class="team-member ">
<div class="row margin-0">
<div class="team-info" style="text-align:center; border: 1.2pt solid #1874BF;">
<img src="#ViewBag.Badges[i].ImageURL" style="width:80%;" class="img-fluid" />
</div>
<div class="team-info" style="text-align:center; width:100%;">
#ViewBag.Badges[i].Label
<br />
<input id="Badge_#ViewBag.Badges[i].ID" data-badgeid="#ViewBag.Badges[i].ID" data-label="#ViewBag.Badges[i].Label" class="checkBoxBadgeClass" type="checkbox" />
</div>
</div>
</div>
</div>
}
}
</div>
</div>
</div>
</div>
<div class="modal-footer">
<i class="fa fa-plus-circle"></i> #Resource.Edit
</div>
</div>
</div>
</div>
and this is my jquery:
currentStudentId = null;
currentAssignedBadge = [];
$('#BadgeAssignmentTable').dataTable({
responsive: true,
aLengthMenu: [
[10, 25, 50, 100, -1],
[10, 25, 50, 100, "All"]
]
});
$(".modalLink").on("click", function () {
var $pencil = $(this);
var studentId = $pencil.data('studentid');
var badges = $pencil.data('badges');
var studentName = $pencil.data("studentname");
PrepareBadgesModal(studentId, badges.split(","), studentName);
});
PrepareBadgesModal = function (studentId, assignedBadges, studentName) {
currentStudentId = studentId;
console.log(assignedBadges);
currentAssignedBadge = [];
$.each(assignedBadges, function (k, v) { return currentAssignedBadge.push(parseInt(v, 10)); });
$.each(assignedBadges, function (k, v) {
var $badge = $("#Badge_" + v);
$badge.prop("checked", true);
var label = $badge.data("label");
$badge.on("click", function (event) {
var res = ConfirmRemoveBadge($(this), label, studentName);
event.stopPropagation();
});
});
}
ConfirmRemoveBadge = function ($badge, label, studentName) {
var txt = "ATTENTION\r\rÊtes-vous certain de vouloir retirer le badge \"" + label + "\" à " + studentName + "?";
var r = confirm(txt);
if (r == true) {
$badge.prop("checked", false);
$badge.unbind("click");
} else {
$badge.prop("checked", true);
}
}
$("#AssignBadges").click(function () {
ModifyBadgesAction();
});
ModifyBadgesAction = function (badgeList) {
var selBadgeLst = $('input[id^=Badge_]:checked').map(function (k, v) { return parseInt($(v).data('badgeid'), 10); });
//TODO: Close the modal
var removedLst = $.grep(currentAssignedBadge, function (v, k) {
return $.grep(selBadgeLst, function (vv, kk) {
return v == vv;
}).length == 0;
});
var AddedList = $.grep(selBadgeLst, function (v, k) {
return $.grep(currentAssignedBadge, function (vv, kk) {
return v == vv;
}).length == 0;
});
var jsonData = JSON.stringify({ studentId : currentStudentId, AddedList: AddedList, removedLst: removedLst });
$.ajax({
contentType: 'application/json; charset=utf-8',
dataType: 'json',
type: 'POST',
url: '/Badges/ModifyBadgesAction',
data: jsonData,
success: function (data, textStatus, jqXHR) {
//console.log(data, textStatus, jqXHR);
if (data.code == 0) {
ApplyBadgeActionSuccess(data);
}
else {
ApplyBadgeActionError(data);
}
},
error: function (jqXHR, textStatus, errorThrown) {
ApplyBadgeActionError({ code: jqXHR.status, message: "Technical Error", data: [{ jqXHR: jqXHR, error: errorThrown }] });
}
});
};
ApplyBadgeActionSuccess = function (data) {
alert(data.message);
window.location.reload(true);
}
ApplyBadgeActionError = function (data) {
alert(data.message);
}
I am trying toggle/check according specific permissions with array set id's - to set permissions for users according to their user role. for an example an admin would have permissions to create users, delete, and update. My struggle with the code i've posted below is that it toggles all permissions instead of ones passed into formControl im not sure if im doing right.
public userList: Array < User > ;
public principalList: Array < Principal > ;
public permissionList: Array < PermissionItem > ;
public groupPermissionList: Array < PermissionGroup > ;
public permIdArr: Array < number > = [];
public permGrpIdArr: Array < number > = [];
public isSelected = false;
public updatePermsList(ev, id: number) {
console.log(ev.target.checked, id);
if (ev.target.checked) {
this.permIdArr.push(id);
console.log(this.permIdArr);
} else {
this.permIdArr = this.permIdArr.filter(pId => {
return pId !== id;
});
}
}
public updateGrpPermsList(event, id: number) {
if (id === 1) {
let grpid;
this.groupPermissionList.map(i => {
const per = i.permissions;
per.forEach(e => {
grpid = e.id;
this.permGrpIdArr.push(grpid);
});
});
} else if (id === 2) {
console.log('2nd');
} else {
console.log('3rd');
}
this.createNewUserForm.controls['app_user_permissions'].setValue(this.permGrpIdArr);
}
<div class="user-new-container p24">
<div [class.updating]="submitting">
<form [formGroup]="createNewUserForm" (ngSubmit)="onSubmit(createNewUserForm.value)" class="updater">
<div class="row">
<div class="col-lg-6">
<div *ngIf="groupPermissionList" class="row perms">
<div class="col-lg-12">
<h3 class="mb24">Group Permissions</h3>
<div class="row">
<div *ngFor="let p of groupPermissionList;let i = index" class="col-lg-4">
<div class="form-group row">
<div class="col-lg-6 col-sm-10 col-xs-10 toggle-switch">
<input (click)="updateGrpPermsList($event, p.id)" value="p.id" type="checkbox" id="permGrp_{{i}}">
<label for="permGrp_{{i}}">{{p.name}}</label>
</div>
</div>
</div>
</div>
</div>
</div>
<br>
<div *ngIf="permissionList" class="row perms">
<div class="col-lg-12">
<h3 class="mb24">Permissions</h3>
<div class="row">
<div *ngFor="let p of permissionList;let idx = index" class="col-lg-4">
<div class="form-group row">
<div class="col-lg-6 col-sm-10 col-xs-10 toggle-switch">
<input (change)="updatePermsList($event, p.id)" formControlName="app_user_permissions" type="checkbox" [checked]="val" id="perm_{{idx}}">
<label for="perm_{{idx}}">{{p.name}}</label>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
demo:
https://jsfiddle.net/8hh0p0ej/
In this demo,there is a selected attribute in items,which control the item selected or not and "allSelected".
Question:
When I use it in my project,the content of items will be gotten form mysql,there is no selected field,the status of one item doesn't need to be recorded,so I don't want to add this field,how to accomplish "Allselected" in this situation?
You can add a selected member to the data after it is fetched.
var vm = new Vue({
el: "#app",
data: {
items: []
},
methods: {
fillIn: function(index, n) {
this.items[index].num = n;
}
},
computed: {
nums: function() {
return [1, 2, 3, 4, 5];
},
allSelected: {
get: function() {
for (var i = 0, length = this.items.length; i < length; i++) {
if (this.items[i].selected === false) {
return false;
}
}
return true;
},
set: function(val) {
for (var i = 0, length = this.items.length; i < length; i++) {
this.items[i].selected = val;
}
}
},
sum: function() {
var totalAmount = 0;
for (var i = 0, length = this.items.length; i < length; i++) {
var item = this.items[i];
if (item.selected === true) {
totalAmount += item.price * item.num;
}
}
return totalAmount;
}
}
});
// Data as it might come from mysql
mysqlData = [{
message: 'Apple',
num: 1,
price: 5
}, {
message: 'Peach',
num: 1,
price: 10
}, {
message: 'Orange',
num: 1,
price: 15
}, {
message: 'Pear',
num: 1,
price: 20
}];
// Modify the data when we put it in the vm
vm.$set('items', mysqlData.map((item) => {
item.selected = false;
return item;
}));
<link href="//cdnjs.cloudflare.com/ajax/libs/tether/1.3.7/css/tether.min.css" rel="stylesheet" />
<script src="//cdnjs.cloudflare.com/ajax/libs/tether/1.3.7/js/tether.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="//cdn.bootcss.com/bootstrap/4.0.0-alpha.3/css/bootstrap.min.css" rel="stylesheet" />
<script src="//cdn.bootcss.com/bootstrap/4.0.0-alpha.3/js/bootstrap.min.js"></script>
<script src="//cdn.bootcss.com/vue/1.0.26/vue.min.js"></script>
<div class="container">
<div class="card">
<h3 class="card-header">Cart</h3>
<div class="card-block">
<div id="app">
<div class="row">
<div class="col-xs-3">
<label class="c-input c-checkbox">
<input type="checkbox" v-model="allSelected">Select All
<span class="c-indicator"></span>
</label>
</div>
<div class="col-xs-2">
Goods
</div>
<div class="col-xs-5">
Number
</div>
<div class="col-xs-2">
Money
</div>
</div>
<form>
<div class="row" v-for="(index, item) in items">
<div class="col-xs-3">
<label class="c-input c-checkbox">
<input type="checkbox" v-model="item.selected">
<span class="c-indicator"></span>
</label>
</div>
<div class="col-xs-2">
{{ item.message }}
</div>
<div class="col-xs-5">
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-text="item.num">
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
<li v-for="n in nums">
<a class="dropdown-item" #click="fillIn(index, n)">{{n}}个</a>
</li>
</ul>
</div>
</div>
<div class="col-xs-2">
{{ item.price * item.num }}
</div>
</div>
<div class="row">
<div class="col-xs-3">
Sum
</div>
<div class="col-xs-2">
</div>
<div class="col-xs-5">
</div>
<div class="col-xs-2">
{{ sum }}
</div>
</div>
<button type="submit" class="btn btn-primary" :disabled="sum === 0">Submit</button>
</form>
</div>
</div>
</div>
</div>
You could keep a separate object with the id of the object as a key and a Boolean value, that represents if the item is selected or not.
The items data would only have, message, num and price
While the selected data would have itemid and selected
can someone explain me why this execute only first time? It should remove item from minishopping cart, but it works only first time.
This is html section:
<div data-itemid="#item.Id" class="item #(i == 0 ? "first" : null) row">
<div class="remove">
<input class="remove-item-cart-btn" type="button" value="Remove" data-itemid="#item.Id" />
</div>
I have Action in my controler:
[HttpPost]
public ActionResult RemoveProductFromCart_Catalog(int id)
{
var shoppingCartItem = _workContext.CurrentCustomer.ShoppingCartItems
.Where(sci => sci.ShoppingCartType == ShoppingCartType.ShoppingCart && sci.Id == id)
.LimitPerStore(_storeContext.CurrentStore.Id).FirstOrDefault();
_shoppingCartService.DeleteShoppingCartItem(shoppingCartItem, ensureOnlyActiveCheckoutAttributes: true);
//display notification message and update appropriate blocks
var updatetopcartsectionhtml = string.Format(_localizationService.GetResource("ShoppingCart.HeaderQuantity"),
_workContext.CurrentCustomer.ShoppingCartItems
.Where(sci => sci.ShoppingCartType == ShoppingCartType.ShoppingCart)
.LimitPerStore(_storeContext.CurrentStore.Id)
.ToList()
.GetTotalProducts());
var updateflyoutcartsectionhtml = _shoppingCartSettings.MiniShoppingCartEnabled
? this.RenderPartialViewToString("FlyoutShoppingCart", PrepareMiniShoppingCartModel())
: "";
return Json(new
{
success = true,
message = string.Format(_localizationService.GetResource("Products.ProductHasBeenAddedToTheCart.Link"), Url.RouteUrl("ShoppingCart")),
updatetopcartsectionhtml = updatetopcartsectionhtml,
updateflyoutcartsectionhtml = updateflyoutcartsectionhtml
});
}
and this is js function:
$(function() {
$(".mini-shopping-cart").on("click", '.remove-item-cart-btn', function (e)
{
alert("test");
var $this = $(this);
$.ajax({
url: '#Url.Action("RemoveProductFromCart_Catalog", "ShoppingCart")',
cache: false,
data:
{
id: $this.data('itemid')
},
success: function (data, textStatus, jqXHR)
{
$("#flyout-cart").replaceWith(data.updateflyoutcartsectionhtml);
jQuery.each($(".cart-qty"), function (i, val) {
$(val).text(data.updatetopcartsectionhtml);
});
}
});
e.preventDefault();
});
});
I am new in js so dont blame me(a lot).
Thanks in advance!
This is the whole html section:
<div id="flyout-cart" class="flyout-cart">
<div class="mini-shopping-cart">
<div class="count">
#if (Model.TotalProducts == 0)
{
#T("ShoppingCart.Mini.NoItems")
}
else
{
#Html.Raw(string.Format(T("ShoppingCart.Mini.ItemsText").Text, string.Format("{1}", Url.RouteUrl("ShoppingCart"), string.Format(T("ShoppingCart.Mini.Items").Text, Model.TotalProducts))))
}
</div>
#if (Model.TotalProducts > 0)
{
<div class="items">
#for (int i = 0; i < Model.Items.Count; i++)
{
var item = Model.Items[i];
<div data-itemid="#item.Id" class="item #(i == 0 ? "first" : null)">
#if (Model.ShowProductImages)
{
<div class="picture">
<a href="#Url.RouteUrl("Product", new { SeName = item.ProductSeName })" title="#item.Picture.Title">
<img alt="#item.Picture.AlternateText" src="#item.Picture.ImageUrl" title="#item.Picture.Title" />
</a>
</div>
}
<div class="product">
<div class="name">
#item.ProductName
</div>
#if (!String.IsNullOrEmpty(item.AttributeInfo))
{
<div class="attributes">
#Html.Raw(item.AttributeInfo)
</div>
}
<div class="price">#T("ShoppingCart.Mini.UnitPrice"): <span>#item.UnitPrice</span></div>
<div class="quantity">#T("ShoppingCart.Mini.Quantity"): <span>#item.Quantity</span></div>
</div>
<div class="remove">
<input class="remove-item-cart-btn" type="button" value="Remove" data-itemid="#item.Id" />
</div>
</div>
}
</div>
<div class="totals">#T("ShoppingCart.Totals.SubTotal"): <strong>#Model.SubTotal</strong></div>
<div class="buttons">
#if (Model.DisplayShoppingCartButton)
{
<input type="button" value="#T("ShoppingCart.Mini.ViewCart")" class="button-1 cart-button" onclick="setLocation('#(Url.RouteUrl("ShoppingCart"))')" />
}
#if (Model.DisplayCheckoutButton)
{
var checkoutUrl = "";
if (Model.AnonymousCheckoutAllowed && Model.CurrentCustomerIsGuest)
{
checkoutUrl = Url.RouteUrl("LoginCheckoutAsGuest", new { returnUrl = Url.RouteUrl("ShoppingCart") });
}
else
{
checkoutUrl = Url.RouteUrl("Checkout");
}
<input type="button" value="#T("Checkout.Button")" class="button-1 checkout-button" onclick="setLocation('#checkoutUrl')" />
}
</div>
}
</div>