When I create a dynamic dropdown using select2 it breaks - jquery-select2

I have a table which has the column "genre" which has a select box which is populated using Select2, and I have a button which adds a new row to the table, once I add a new row to the table, I try to populate the Genre using select2 as well but its buggy, it results in the new select dropdown not being selectable.
Have a look at my JSFiddle here: https://jsfiddle.net/hm3w7jtz/3/
In order to get to the bug, Add a new group and then you will notice that the new row genre is not selectable.
https://jsfiddle.net/szjd6gu4/2/
Code
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/select2#4.0.13/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/select2#4.0.13/dist/js/select2.min.js"></script>
</head>
<h3> Movies </h3>
<table class="my_table" id="movies" border="1px" style="border-collapse: collapse;">
<thead>
<tr><b>
<td>Group</td>
<td>Genre</td>
<td>Movie Name</td>
<td>Imdb</td>
<td>Rotten Tomato</td>
<td>Lead Actress</td>
<td>Lead Actor</td>
<td>Year of Release</td>
<td>Revenue</td>
<td>Budget</td>
</tr></b>
</thead>
<tbody>
<tr class="group-row">
<td class="nr"><input type="text" placeholder="" size="9"><button id="btn" class="group" style="float:right;">+</button>
</td>
<td><select id="genre" class='genre' style="width:150px;"></select></td>
<td><input type="text" size="7" placeholder=""></td>
<td><input type="text" size="7" placeholder=""></td>
<td><input type="text" size="7" placeholder=""></td>
<td><input type="text" size="7" placeholder=""></td>
<td><input type="text" size="10" placeholder=""></td>
<td><input type="text" size="7" placeholder=""></td>
<td><input type="text" size="7" placeholder=""></td>
<td><input type="text" size="7" placeholder=""></td>
</tr>
</tbody>
</table>
<script>
$(document).ready(function() {
var genre = ['Action', 'Adventure', 'Fantasy', 'Anime', 'Romance'];
$(".genre").select2({
data: genre
});
});
var row ="<td class='nr'><input type='text' placeholder='' size='9'><button id='btn' class='group' style='float:right;'>+</button></td><td><select id='genre' class='genre' style='width:150px;'></select></td><td><input type='text' size='7' placeholder=''></td><td><input type='text' size='7' placeholder=''></td><td><input type='text' size='7' placeholder=''></td><td><input type='text' size='7' placeholder=''></td><td><input type='text' size='10' placeholder=''></td><td><input type='text' size='7' placeholder=''></td><td><input type='text' size='7' placeholder=''></td><td><input type='text' size='7' placeholder=''></td>";
const $groupRow = $("<tr>", {
class: "group-row"
}).append(row);
const tableBody = $("#movies tbody");
tableBody.on('click', '.group', (e) => {
tableBody.append($groupRow.clone());
$(".genre").select2({
data: genre
});
});
</script>

There are 2 problems with your code:
1) Remove id="genre" from both of your Selects
<select id="genre" class='genre' style="width:150px;"></select>
2) You need to move the line with the Array right before the $(document).ready function:
//BEFORE
$(document).ready(function() {
var genre = ['Action', 'Adventure', 'Fantasy', 'Anime', 'Romance'];
$(".genre").select2({
data: genre
});
});
//AFTER
var genre = ['Action', 'Adventure', 'Fantasy', 'Anime', 'Romance'];
$(document).ready(function() {
$(".genre").select2({
data: genre
});
});
var genre = ['Action', 'Adventure', 'Fantasy', 'Anime', 'Romance'];
$(document).ready(function() {
$(".genre").select2({
data: genre
});
});
var row ="<td class='nr'><input type='text' placeholder='' size='9'><button id='btn' class='group' style='float:right;'>+</button></td><td><select class='genre' style='width:150px;'></select></td><td><input type='text' size='7' placeholder=''></td><td><input type='text' size='7' placeholder=''></td><td><input type='text' size='7' placeholder=''></td><td><input type='text' size='7' placeholder=''></td><td><input type='text' size='10' placeholder=''></td><td><input type='text' size='7' placeholder=''></td><td><input type='text' size='7' placeholder=''></td><td><input type='text' size='7' placeholder=''></td>";
const $groupRow = $("<tr>", {
class: "group-row"
}).append(row);
const tableBody = $("#movies tbody");
tableBody.on('click', '.group', (e) => {
tableBody.append($groupRow.clone());
$(".genre").select2({
data: genre
});
});
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/select2#4.0.13/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/select2#4.0.13/dist/js/select2.min.js"></script>
</head>
<h3> Movies </h3>
<table class="my_table" id="movies" border="1px" style="border-collapse: collapse;">
<thead>
<tr><b>
<td>Group</td>
<td>Genre</td>
<td>Movie Name</td>
<td>Imdb</td>
<td>Rotten Tomato</td>
<td>Lead Actress</td>
<td>Lead Actor</td>
<td>Year of Release</td>
<td>Revenue</td>
<td>Budget</td>
</tr></b>
</thead>
<tbody>
<tr class="group-row">
<td class="nr"><input type="text" placeholder="" size="9"><button id="btn" class="group" style="float:right;">+</button>
</td>
<td><select class='genre' style="width:150px;"></select></td>
<td><input type="text" size="7" placeholder=""></td>
<td><input type="text" size="7" placeholder=""></td>
<td><input type="text" size="7" placeholder=""></td>
<td><input type="text" size="7" placeholder=""></td>
<td><input type="text" size="10" placeholder=""></td>
<td><input type="text" size="7" placeholder=""></td>
<td><input type="text" size="7" placeholder=""></td>
<td><input type="text" size="7" placeholder=""></td>
</tr>
</tbody>
</table>

Related

Add text boxes data to grid temporarily using knockout.js

Html code
<label class="control-label">Contact Person</label>
<input class="form-control" type="text" placeholder="Enter Contact name" data-bind="value: ContactPerson" data-validate='{"required":"true"}'><br />
<label class="control-label">ContactNo</label>
<input class="form-control" type="tel" data-bind="value: ContactNo" placeholder="ContactNo" data-validate='{"required":"true"}'><br />
<label class="control-label">E-Mail</label>
<input class="form-control" type="email" data-bind="value: Email" placeholder="Email" data-validate='{"required":"true","email":"true"}'><br />
<table class="table table-hover table-bordered" id="listTable">
<thead>
<tr>
<th>ContactPerson</th>
<th>ContactNo</th>
<th>Email</th>
<th></th>
</tr>
</thead>
<tbody data-bind="template:{name: 'Process-list',
foreach: rootViewModel.BodyContent.ProcessList }">
</tbody>
</table>
when I click on add button the data in the three text box should bind to grid ,
and when i click on delete button of row in grid it should disappear for this i need viewmodel.
Thanks
Here's a quick view model that does the requirements. I selected ContactNo as the primary key since they're supposed to be unique. You can use ids if needed instead. It would also be a good idea to run your validations before add method is called.
var viewModel = function(){
var self = this;
self.ContactPerson = ko.observable();
self.ContactNo = ko.observable();
self.Email = ko.observable();
self.ProcessList = ko.observableArray();
self.add = function(){
self.ProcessList.push({
ContactPerson: self.ContactPerson(),
ContactNo: self.ContactNo(),
Email: self.Email(),
});
self.ContactPerson('');
self.ContactNo('');
self.Email('');
};
self.delete = function(data, event){
self.ProcessList.remove(function(listObject){
return listObject.ContactNo === data.ContactNo;
});
};
};
ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<label class="control-label">Contact Person</label>
<input class="form-control" type="text" placeholder="Enter Contact name" data-bind="value: ContactPerson" data-validate='{"required":"true"}'><br />
<label class="control-label">ContactNo</label>
<input class="form-control" type="tel" data-bind="value: ContactNo" placeholder="ContactNo" data-validate='{"required":"true"}'><br />
<label class="control-label">E-Mail</label>
<input class="form-control" type="email" data-bind="value: Email" placeholder="Email" data-validate='{"required":"true","email":"true"}'><br />
<button data-bind="click: add">Add Data</button>
<table class="table table-hover table-bordered" id="listTable">
<thead>
<tr>
<th>ContactPerson</th>
<th>ContactNo</th>
<th>Email</th>
<th></th>
</tr>
</thead>
<tbody data-bind="template:{name: 'Process-list',
foreach: ProcessList }">
</tbody>
</tbody>
</table>
<script type="text/html" id="Process-list">
<tr>
<td data-bind="text: ContactPerson"></td>
<td data-bind="text: ContactNo"></td>
<td data-bind="text: Email"></td>
<td><button data-bind="click: $root.delete">Delete</button></td>
</tr>
</script>

Executing the same partial view multiple times in the same view

I am new to MVC and would like some help.
I have a view (below) which displays the products, next to each other. Till here everything is fine.
#foreach (var item in Model)
{
<a href="#Url.Action("showProductDetails", "Shared", new { ProductID = item.ProductID }, null)">
<div class='OutsideDiv' >
<table class='DivBorder'>
<tr >
<td class='title'>
#item.ProductName
</td>
</tr>
<tr >
<td class='imageBox'>
<img alt='' src="#item.ImageURL" />
</td>
</tr>
<tr>
<td class='title'>
#Html.Action("showAverageRating", "Rating" , new { ProductID = item.ProductID } ) *************
</td>
</tr>
<tr>
<td class='desc'>
#item.Description
</td>
</tr>
<tr>
<td class='price'>
€ #item.Price
</td>
</tr>
</table>
</div>
<script type='text/javascript'> $('.DivBorder').mouseover(function () { $(this).css('border-color', '#0953cb'); $(this).css('background-color', '#eaeaea'); }); $('.DivBorder').mouseout(function () { $(this).css('border-color', '#bdbdbd'); $(this).css('background-color', '#f6f6f6'); });</script>
</a>
}
In the line marked with '****' above I am calling another view (showAverageRating) which for now is just displaying 5 rating stars with the first 3 starts selected.
<input class="star " name="adv1" type="radio" />
<input class="star " name="adv1" type="radio" />
<input checked="checked" class="star " name="adv1" type="radio" />
<input class="star " name="adv1" type="radio" />
<input class="star " name="adv1" type="radio" />
The problem is that on the second item, when the rating stars view (above partial view) is called again, the stars are displayed next to the stars of the first product, picture below.
I think I have to use something else rather than Html.Action?
EDIT : showAverageRating Code
public ActionResult showAverageRating(int ProductID)
{
decimal averageRating = new RatingsService.RatingsClient().getAverageRating(ProductID);
ViewData["averageRating"] = averageRating;
return PartialView();
}
The problem was that the name of the stars where identical, so I included the productID with their name, like below.
showAverageRating partial view
#{decimal averageRating = ViewBag.averageRating;}
#{int productID = ViewBag.productID;}
<div id="averageRating" >
<input class="star" name="star+#productID" type="radio" />
<input class="star " name="star+#productID" type="radio" />
<input checked="checked" class="star " name="star+#productID" type="radio" />
<input class="star " name="star+#productID" type="radio" />
<input class="star " name="star+#productID" type="radio" />
</div>

access to input value which has array form name attribute

I have inputtext filed in my gsp llike this :
<tr class="context">
<td width="5%" ><a class="addButton" href="#" style="display:none;" >+</a></td>
<td width="60%"><input type="text" name="iwd0_description" value="" id="iwd0_description" /></td>
<td width="10%"><input type="text" name="iwd0_tax" value="" id="iwd0_tax" /></td>
<td width="10%"><input type="text" name="iwd0_discount" value="" id="iwd0_discount" /></td>
<td width="10%"><input type="null" name="iwd0_total" value="0" required="" id="iwd0_total" /></td>
<td width="5%" ><a class="deleteButton" href="#" style="display:none;" >-</a></td>
</tr>
<tr class="context">
<td width="5%" ><a class="addButton" href="#" style="display:none;" >+</a></td>
<td width="60%"><input type="text" name="iwd1_description" value="" id="iwd1_description" /></td>
<td width="10%"><input type="text" name="iwd1_tax" value="" id="iwd1_tax" /></td>
<td width="10%"><input type="text" name="iwd1_discount" value="" id="iwd1_discount" /></td>
<td width="10%"><input type="null" name="iwd1_total" value="0" required="" id="iwd1_total" /></td>
<td width="5%" ><a class="deleteButton" href="#" style="display:none;" >-</a></td>
</tr>
How can I access to input value in my controller?
Form values are sent over HTTP using request parameters (for GET requests), with the input name attribute used to set the parameter "key". So your HTTP request will have the following params: ?iwd0_tax=userInput1&iwd0_discount=userInput2 etc.
Grails makes request parameters available by the params var in controllers:
def iwd0_tax = params.iwd0_tax
Grails can also populate a bean/class from the request params automatically. The bean is called a command object. See details in the Grails docs.
def i = 0
while (params."iwd${i}_tax") {
println 'tax'+"${i}" + params."iwd${i}_tax"
i++
}

How to fetch data in arrayList from jsp

This is my form in jsp
<form action="submit">
<tr class="row" id="item1">
<td><input type="text" name="type" class="type" style="width: 50px"/></td>
<td><input type="text" name="color" class="color" style="width: 50px"/></td>
<td><input type="text" name="qty" class="qty" style="width: 50px"/></td>
<td><input type="text" name="unitprice" class="unitPrice" style="width: 50px"/></td>
</tr>
...
<tr class="row" id="itemN">
<td><input type="text" name="type" class="type" style="width: 50px"/></td>
<td><input type="text" name="color" class="color" style="width: 50px"/></td>
<td><input type="text" name="qty" class="qty" style="width: 50px"/></td>
<td><input type="text" name="unitprice" class="unitPrice" style="width: 50px"/></td>
</tr>
</form>
I want to fetch data which may contain 1 to N items and each item contais type color qty and unitprice. I want to store all these data in ArrayList variable.
How to do this?
What you need is Tabular Input

Knockout Validation is not working

It may be the easiest question but I am not able to resolve this. The validation on my page is not working. Everytime I am submitting the page leaving all the input fields blank, an alert is generated saying 'Failed'. And if I enter all the fields with some value data is successfully submitted.
Here is my HTML :
#{
ViewBag.Title = "Exercise10";
}
<html>
<head>
<script src="../../Scripts/jquery-1.6.2.js" type="text/javascript"></script>
<script src="../../Scripts/knockout-2.2.1.js" type="text/javascript"></script>
<script src="../../Scripts/knockout.mapping-latest.js" type="text/javascript"></script>
<script src="../../Scripts/json2.js" type="text/javascript"></script>
<link href="../../Content/ExerciseStyle.css" rel="stylesheet" type="text/css" />
<script src="../../Scripts/Popup.js" type="text/javascript"></script>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.0/themes/base/jquery- ui.css" />
<script src="http://code.jquery.com/ui/1.10.0/jquery-ui.js"></script>
<script src="../../Scripts/DatePicker.js" type="text/javascript"></script>
<script src="../../Scripts/knockout.validation.js" type="text/javascript"></script>
<script src="../../Scripts/knockout-validator.js" type="text/javascript"></script>
<script src="../../Scripts/knockout-validator-extensions.js" type="text/javascript"></script>
<link href="../../Scripts/extensions.css" rel="stylesheet" type="text/css" />
</head>
<body>
<form action="" method="post">
<div id="MainArea">
<table id="tbllist" align="center" style="margin-left: 15px; width: 96%; margin- right: 15px;">
<tr>
<th colspan="3" align="left">
<div id="title_p">
Enter Following Entries</div>
</th>
</tr>
<tr>
<td align="right" style="width: 40%;">
<b>Name :</b>
</td>
<td align="left" style="width: 17%;">
<input data-bind="value: EmployeeName" placeholder="Employee Name" class="txt"
type="text" />
</td>
<td align="left">
</td>
</tr>
<tr>
<td align="right">
<b>Emp# :</b>
</td>
<td align="left">
<input data-bind="value: EmployeeCode" placeholder="Employee Code" style="width: 200px;"
type="text" />
</td>
<td align="left">
</td>
</tr>
<tr>
<td align="right">
<b>Date of Birth :</b>
</td>
<td align="left">
<input data-bind="value: Dob" id="datepicker" placeholder="Date of Birth" style="width: 200px;"
type="text" /><span>(dd/mm/yyyy)</span>
</td>
<td align="left">
</td>
</tr>
<tr>
<td align="right">
<b>Age (18-60):</b>
</td>
<td align="left">
<input data-bind="value: Age" style="width: 200px;" placeholder="Age Range (18-60)"
type="number" min="18" max="60" />
</td>
<td align="left">
</td>
</tr>
<tr>
<td align="right">
<b>Contact Number :</b>
</td>
<td align="left">
<input data-bind="value: ContactNumber" placeholder="Contact Number" style="width: 200px;"
type="text" />
</td>
<td align="left">
</td>
</tr>
<tr>
<td align="right">
<b>Email :</b>
</td>
<td align="left">
<input data-bind="value: EmailID" placeholder="Email ID" style="width: 200px;"
type="email" />
</td>
<td align="left">
</td>
</tr>
<tr>
<td align="right">
<b>Address :</b>
</td>
<td align="left">
<input data-bind="value: Address" placeholder="Address" style="width: 200px;"
type="text" />
</td>
<td align="left">
</td>
</tr>
<tr>
<td align="right">
<b>City :</b>
</td>
<td align="left">
<select data-bind="value: City" style="width: 200px;">
<option value="Noida">New Delhi</option>
<option value="Noida">Noida</option>
<option value="Noida">Mumbai</option>
</select>
</td>
<td align="left">
</td>
</tr>
<tr>
<td align="right">
<b>Marital Status :</b>
</td>
<td align="left">
<input data-bind="checked: MaritalStatus" checked="checked" name="rdb" type="radio" /><span>UnMarried</span>
<input data-bind="checked: MaritalStatus" checked="checked" name="rdb" type="radio" checked="checked" /><span>Married</span>
</td>
<td align="left">
</td>
</tr>
<tr>
<td align="right">
<b>Any Employee Reference :</b>
</td>
<td align="left">
<input data-bind="checked: Is_Reference" type="checkbox" />yes
</td>
<td align="left">
</td>
</tr>
</table>
<table style="width: 99%; margin-right: 20px; padding: 5px;">
<tr align="right">
<td>
<button data-bind="click :$root.save" class="button">Save</button>
<input type="button" id="btnCancel" class="button" value="Cancel" onclick="JavaScript:closePopup();" />
</td>
</tr>
</table>
</div>
</form>
And My View Model (continued from the above):
<script type="text/javascript">
//....................................................//
var EmpViewModel = function () {
//Make the self as 'this' reference
var self = this;
//Declare observable which will be bind with UI
self.EmployeeCode = ko.observable("").extend({ required: true });
self.EmployeeName = ko.observable("").extend({ required: { message: 'Please supply your Name.'} });
self.Dob = ko.observable("");
self.Age = ko.observable("").extend({number :true});
self.ContactNumber = ko.observable("");
self.EmailID = ko.observable("");
self.Address = ko.observable("");
self.MaritalStatus = ko.observable("");
self.City = ko.observable("");
self.Is_Reference = ko.observable("");
//The Object which stored data entered in the observables
var EmpData = {
EmpCode: self.EmployeeCode,
EmpName: self.EmployeeName,
Dob: self.Dob,
Age: self.Age,
ContactNumber: self.ContactNumber,
MaritalStatus: self.MaritalStatus,
EmailID: self.EmailID,
Address: self.Address,
City: self.City,
Is_Reference: self.Is_Reference
};
//Declare an ObservableArray for Storing the JSON Response
self.Employees = ko.observableArray([]);
//Function to perform POST (insert Employee) operation
self.save = function () {
//Ajax call to Insert the Employee
$.ajax({
type: "POST",
url: "/Exercise/Save/",
data: ko.toJSON(this), //Convert the Observable Data into JSON
contentType: "application/json",
success: function (data) {
alert(data);
},
error: function () {
alert("Failed");
}
});
//Ends Here
};
}
ko.applyBindings(new EmpViewModel());
</script>
Knockout-validation shows validation messages only if the fields are modified. Therefore you should check on submit if all fields are valid and show all errors if not.
self.errors = ko.validation.group(this, { deep: true, observable: false });
//Function to perform POST (insert Employee) operation
self.save = function () {
// check if valid
if(self.errors().length > 0) {
self.errors.showAllMessages();
return;
}
//Ajax call to Insert the Employee
$.ajax({
type: "POST",
url: "/Exercise/Save/",
data: ko.toJSON(this), //Convert the Observable Data into JSON
contentType: "application/json",
success: function (data) {
alert(data);
},
error: function () {
alert("Failed");
}
});
//Ends Here
};
I have created a fiddle to show that: http://jsfiddle.net/delixfe/tSzYf/2/

Resources