One data binding works well and display automatic data but when I add another copying the same pattern of first, second gives error and do not work. So in below example if I do comment anyone, another do not work.
HTML CODE:
<table>
<thead>
<tr><th>Item Name</th><th>Price</th></tr>
</thead>
<tbody data-bind="foreach: itemsdisplay">
<tr>
<td data-bind="text: Name" />
<td data-bind="text: Price" />
</tr>
</tbody>
</table>
<table>
<thead>
<tr><th colspan="3" style="color:#06C">Stock Market Metal Rates</th></tr>
</thead>
<tbody data-bind="foreach: MetalDisplay">
<tr>
<td data-bind="text: Name" />
<td data-bind="text: Price" />
<td data-bind="text: Dated" />
</tr>
</tbody>
</table>
This is my JS code:
function GetProducts(handleData) {
$.ajax({
url: 'form.php',
type: "post",
data: '',
dataType: 'json',
success: function(data){
handleData(data);
},
error:function(data){
alert('Failed');
}
});
}
function GetMetals(handleData) {
$.ajax({
url: 'form2.php',
type: "post",
data: '',
dataType: 'json',
success: function(data){
handleData(data);
},
error:function(data){
alert('Failed');
}
});
}
$(function () {
var ItemDisplayViewModel = function() {
var self = this;
self.itemsdisplay = ko.observableArray();
self.update = function() {
GetProducts(function(output){
self.itemsdisplay.removeAll();
$.each(output, function (i) {
self.itemsdisplay.push(new product(output[i]));
});
});
}
};
var MetalViewModel = function() {
var self = this;
self.MetalDisplay = ko.observableArray();
self.update = function() {
GetMetals(function(output){
self.MetalDisplay.removeAll();
$.each(output, function (i) {
self.MetalDisplay.push(new metals(output[i]));
});
});
}
};
var ItemDisplayViewModel = new ItemDisplayViewModel();
window.setInterval(ItemDisplayViewModel.update,1000);
ko.applyBindings(ItemDisplayViewModel);
var MetalViewModel = new MetalViewModel();
window.setInterval(MetalViewModel.update,1000);
ko.applyBindings(MetalViewModel);
});
var product = function (data) {
return {
Name: ko.observable(data.Name),
Price: ko.observable(data.Price)
};
};
var metals = function (data) {
return {
Name: ko.observable(data.Name),
Price: ko.observable(data.Price),
Dated: ko.observable(data.Dated)
};
};
Can anyone help please!
You can do the following.
Provide id for both the tables
<table id="item">
<thead>
<tr><th>Item Name</th><th>Price</th></tr>
</thead>
<tbody data-bind="foreach: itemsdisplay">
<tr>
<td data-bind="text: Name" />
<td data-bind="text: Price" />
</tr>
</tbody>
</table>
<table id="metal">
<thead>
<tr><th colspan="3" style="color:#06C">Stock Market Metal Rates</th></tr>
</thead>
<tbody data-bind="foreach: MetalDisplay">
<tr>
<td data-bind="text: Name" />
<td data-bind="text: Price" />
<td data-bind="text: Dated" />
</tr>
</tbody>
</table>
The modify your script to pass the table element to ko.applyBindings method as below.
var itemDisplayViewModel = new ItemDisplayViewModel();
var x = window.setInterval(itemDisplayViewModel.update,1000);
ko.applyBindings(itemDisplayViewModel,document.getElementById("item"));
var metalViewModel = new MetalViewModel();
var y = window.setInterval(metalViewModel.update,1000);
ko.applyBindings(metalViewModel, document.getElementById("metal"));
Please refer 'Activating knockout' section in http://knockoutjs.com/documentation/observables.html - The part of text from the link given below.
For example, ko.applyBindings(myViewModel, document.getElementById('someElementId')). This restricts the activation to the element with ID someElementId and its descendants, which is useful if you want to have multiple view models and associate each with a different region of the page.
What you are doing does not work. you need to do it like this.
ko.applyBindings(ItemDisplayViewModel,document.getElementById('first_div_id'));
ko.applyBindings(MetalViewModel,document.getElementById('second_div_id'));
Or here is another method
var viewModel = function(){
var self = this
self.Item = ko.observable(new ItemDisplayViewModel())
self.Metal = ko.observable(new MetalViewModel())
}
ko.applyBindings(viewModel)
And now
<table data-bind="with:Item">
.
.
.
</table>
<table data-bind="with:Metal">
.
.
.
</table>
And finally
window.setInterval(viewModel.Item().update, 1000);
window.setInterval(viewModel.Metal().update, 1000);
You can take a look at this post for better understanding.
Related
I have a ViewModel with a parameter List. In the View, the user should be able to add or remove from that list such that the added or removed users are reflected in the POST for that parameter. In JQuery, after clicking an "Add" button, an ajax call returns a UserModel variable, but a simple .append doesn't add to the list.
The other questions I've seen on this issue deal with Partial Views, but this situation updates the table of UserModel without needing a Partial View. It seems like there should be an easy way to do this. Does anyone know how to add the returned UserModel to the List in JQuery so that the List will be returned to the Post with the added models?
<script>
$("#bUser").on('click', function () {
var $addedRecipient = $("#AddedRecipient");
if ($addedRecipient.val() != null && $addedRecipient.val() != "") {
$.ajax({
type: "GET",
url: '#Url.Action("GetFullRecipient", "Message")',
data: { CompanyID: $("#CompanyID").val(), Employee: $addedRecipient.val() },
success: function (data) {
$("#Recipients").append(data);//Not adding to Recipients (Model.List<UserModel>) - is there a simple solution like this?
var bRow = $('<tr></tr>'),
bCell = $('<td style="display:none"></td>').append(data.UserID);
bRow.append(bCell);
bCell = $('<td align="center"></td>').append(data.UserFirstName);
bRow.append(bCell);
bCell = $('<td align="center"></td>').append(data.UserEmail);
bRow.append(bCell);
bCell = $('<td align="center"><input type="button" class="btn btn-info removeRecipient" value="Remove"></td>');
bRow.append(bCell);
$("#bTable tbody").append(bRow);//Works with returned data
$addedRecipient.val("");
},
error: function () {
alert("Recipient could not be added.");
}
});
}
});
</script>
this code worked perfect for me, you just have to go through this list, obviously you have to put the #model directive and a type list Recipient.
#model List<...Models.Recipient>
<input type="button" id="btnAdd" class="btn btn-primary" value="Add"
onclick="myfunction()"/>
<script>
function myfunction() {
$.ajax({
type: 'GET',
contentType:"application/json; charset=utf-8",
url: '#Url.Action("GetFullRecipient","Message")',
data: { CompanyID: $("#CompanyID").val(), Employee:
$addedRecipient.val()},
success: function (response) {
$("#containerData").html(response);
},
error: function (result) {
alert(result);
}
});
}
</script>
<div id="containerData">
<table class="table table-striped table-hover table-bordered">
<thead>
<tr>
<th>Id</th>
<th>Desc_Prod</th>
<th>Cantidad</th>
</tr>
</thead>
<tbody>
#if (Model != null)
{
foreach (var item in Model)
{
<tr>
<td>#item.UserID</td>
<td>#item.UserFirstName</td>
<td>#item.UserEmail</td>
<td><a class="btn btn-danger" href="#Url.Action("DeleteRow","Message", new {item.UserID})">Delete</a></td>
</tr>
}
}
</tbody>
</table>
</div>
The answer here followed the link in freedomn-m's comment. Iterate through the Razor table using a for loop, then use a HiddenFor with the model parameter's ID and a CheckBoxFor as the model parameter's selecting field, and have a submit button with a unique name and value. When a button input is clicked and the value fits a given string, loop through the model and add a user that's not there or subtract a user that is there and return to the View.
<div class="row">
<div class="col-lg-12">
<table class="table table-bordered" id="bTable">
<thead>
<tr>
<th style="display:none"></th>
<th style="display:none"></th>
<th class="text-center">Recipient</th>
<th class="text-center">E-mail</th>
<th class="text-center">Select</th>
</tr>
</thead>
<tbody>
#if (Model.Recipients.Any())
{
for (var i = 0; i < Model.Recipients.Count; i++)
{
<tr>
<td style="display:none">#Html.HiddenFor(m => m.Recipients[i].RecipientUserID)</td>
<td style="display:none">#Html.HiddenFor(m => m.Recipients[i].RecipientCorporateID)</td>
<td align="center">#Model.Recipients[i].RecipientName</td>
<td align="center">#Model.Recipients[i].RecipientEmail</td>
<td align="center">#Html.CheckBoxFor(m => m.Recipients[i].RemoveRecipient)</td>
</tr>
}
}
</tbody>
</table>
</div>
</div>
why when i try to add select2 to new row the new select2 failed to initialize (it shown as select html tag).
Here's my code to create the table :
<table id="tbldet" class="table table-bordered table-striped table-hover" style="width:100%;margin:0 auto;">
<thead>
<tr>
<th><p>Nama Barang</p></th>
<th><p>Harga</p></th>
<th><p>Qty</p></th>
<th><p>Total</p></th>
<th style="width:50px"><p>Aksi</p></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<select class="select2" name="det_brg" style="width:100%;">
</select>
</td>
<td>10000</td>
<td>4</td>
<td>930000</td>
<td><span class="btn btn-danger"><i class="fa fa-remove"></i></span></td>
</tr>
</tbody>
</table>
javascript function to initializeSelect :
function initializeSelect2(selectElementObj) {
selectElementObj.select2({
width: "80%",
tags: true,
language:"id",
ajax: {
url: "controller/barang_list.php",
dataType: "json",
type:"GET",
delay: 250,
data: function (params) {
return {
search: params.term
}
},
processResults: function (data) {
return {
results: $.map(data, function (item) {
return {
id:item.id,
text:item.text
}
})
};
},
cache: false
},
minimumInputLength: 3,
dropdownParent:$("#form-data")
});
};
$(".select2").each(function() {
initializeSelect2($(this));
});
here's the code to add new row :
//create new row
$("#add_row").click(function(e) {
//new row
$("#tbldet").append(
'<tr>\
<td>\
<select class="select2" name="det_brg" style="width:100%;">\
</select>\
</td>\
<td>10000</td>\
<td>4</td>\
<td>930000</td>\
<td><span class="btn btn-danger"><i class="fa fa-remove"></i></span></td>\
</tr>'
);
var newSelect=$(this).closest("tr").find(".select2");
initializeSelect2(newSelect);
})
i suspect there's problem with finding new 'select2' component on new row, but when i use alert(newSelect) it didn't show NULL / Undefined
Your suspicion is correct, your code will never find the new .select2 element. The reason has to do with the way .closest() works. You can investigate that here:
https://api.jquery.com/closest/
But in the mean time:
Change
var newSelect=$(this).closest("tr").find(".select2");
TO
var newSelect=$("#tbldet").find(".select2").last();
I've got two tables. Left side containing all items, right side showing the ordered items. (See picture)
What I want to do:
If an item from the left table is already added on the right table, instead of adding it again, just increase the quantity by one instead. If that's not the case, just add it..
Code:
HTML
<form id="OrderedItemsWithoutBatch" class="orderedDataWithoutBatch">
<table class="orderFormArticlesTable" style="width: 47%;float: right; font-size: 9pt;">
<thead>
<tr>
<th>SKU</th>
<th>Product</th>
<th style="width: 15%">Qty</th>
<th></th>
</tr>
</thead>
<tbody id="orderedItemsVM" data-bind="foreach: orderedItems">
<tr class="clickable" data-bind="css: { alternate: $index()%2 }">
<td data-bind="text: MateriaalSku"> </td>
<td data-bind="text: MateriaalDescription"> </td>
#*<td class="onelineData"><input style="width:2em" type="text" /> [pieces] </td>*#
<td><input class="orderedQty" style="max-width: 15%" data-bind="value: materiaalAantal"/>[pieces]</td>
<td data-bind="click: function() { $parent.orderedItems.remove($data); }">Remove</td>
</tr>
</tbody>
</table>
JS
$(document).ready(function () {
var dataTableForm = $("form.dataWithoutBatch");
var orderedItemsTable = $("form.orderedDataWithoutBatch");
var dataReloading = false;
var currentPage = 0;
//viewModel
var viewModel = {
orderedItems: ko.observableArray(),
items: ko.observableArray(),
sortColumn: ko.observable(),
total: ko.observable()
}
var request = $.post(url, postData);
request.fail(function () {
alert('Failed!');
});
request.always(function () {
listItemsParameterInputs.prop('disabled', false);
$(document.body).removeClass("loading");
dataReloading = false;
if (callback) {
callback();
}
});
request.done(function (data) {
viewModel.total(data.Total);
viewModel.items.removeAll();
for (var index = 0; index < data.Items.length; index++) {
var item = data.Items[index];
if (item.hasOwnProperty("qty")) {
item.qty = ko.observable(item.qty);
}
else {
item.qty = ko.observable("");
}
item.addItem = function () {
//Check if item is already in the table on the right
if(viewModel.orderedItems.indexOf(this) < 0){
viewModel.orderedItems.push(this);
}
else{
// Increase quantity by one.
}
}
viewModel.items.push(item);
}
Instead of using two arrays and removing elements from the second, why don't you use the same array, just add qty variable and show lines only if they satisfy qty()>0
That way, you could just increment the value of qty by one in the first table with this.qty(this.qty()+1); and set the value to 0 in the second when clicking on remove.
Code for your second table should look something like this:
<tbody id="orderedItemsVM" data-bind="foreach: items">
<!-- ko if: qty()>0 -->
<tr class="clickable" >
<td data-bind="text: MateriaalSku"> </td>
<td data-bind="text: MateriaalDescription"> </td>
<td>
<input style="width:2em" type="text" data-bind="value:qty"/>
[pieces]
</td>
<td><a data-bind="click: function() { qty(""); }">Remove</a></td>
</tr>
<!-- /ko -->
</tbody>
more on the if binding at http://knockoutjs.com/documentation/if-binding.html
Cant you just increment the quantity of your observable as follows:
...
else {
// Increase quantity by one.
this.qty(this.qty() += 1)
}
i want to enter only unique Machine_serial_no in my editor templates , user can add Machine_serial_no through browsing a file or can enter manually As shown in below code, i just want to make sure that user shouldnot allow to enter same value twice .your suggestion is always welcome
..Thanks in advance..
//main view
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery-ui-1.9.2.min.js"></script>
<div id="cast">
<tr>
<td> File:</td>
<td><input type="file" id="file" /> </td>
<td> <input type="button" value="Upload" id="btnSubmit" /> </td>
<td></td>
<td></td>
<td></td>
</tr>
<tr class="manualSerial">
<td class="required">Total No of serial no U want to enter:</td>
<td>#Html.TextBoxFor(x => x.count, new { #Value = 0 })</td>
<td colspan="4">
<input type="button" value="Add Serial" id="addserial" />
#*#Html.ActionLink("Add Serial", "AddMachineSerial", "Import", new { #id = "addserial" ,})
#Html.ValidationMessageFor(model => model.serials.Machine_serial_no)*#
</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td id="ShowModel" colspan="6">
<table id="tbl1" style="width:100%;">
<thead>
<tr>
<td>Brand</td>
<td>Machine</td>
<td>Model</td>
<td>Serial No</td>
<td>Mac Address</td>
<td>Action</td>
</tr>
</thead>
</table>
</td>
</tr>
<tr>
<td id="ShowModel" colspan="6">
<div style="height:253px; width:100% ;overflow: auto;">
<table style="width:100%;margin-left:0px;margin-right:0px">
#*<thead>
<tr>
<th style="width:45px;">Brand</th>
<th style="width:90px;">Machine</th>
<th style="width:80px;">Model</th>
<th>Serial No</th>
<th>Mac Address</th>
<th>Action</th>
</tr>
</thead>*#
<tr>
<td colspan="6" id="td_serial"></td>
</tr>
</table>
</div>
</td>
</tr>
//jquery
$('#addserial').click(function () {
var count = $('#count').val();
var i;
if ($('#searchid').val() != '') {
if ($('#count').val() != 0) {
for (i = 0; i < count; i++) {
$.ajax({
type: 'GET',
data: { mid: $('#machineTypes_MTId').val(), modelName: $('#searchid').val(), modelId: $('#searchValue').val() },
url: '#Url.Action("AddMachineSerial","Import")',
success: function (response) {
$('#ShowModel').show();
$('#td_serial').prepend(response);
$('#count').val(0);
}
});
}
}
else {
alert("Enter no of serial you want to enter!")
}
}
else {
alert("select Model First!")
$('#count').val(0);
}
});
//editor Templates /parital view
<script src="#Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
#using (Html.BeginCollectionItem("serialList"))
{
#Html.ValidationSummary(true)
<div id="DeleteTxt1">
<table id="tbl1" style="width:100%;margin-left:0px;margin-right:0px">
<tr class="importitem1">
<td>#Model.brandName</td>
<td>#Model.machineName</td>
<td>#Model.MachineModel</td>
#*<td class="required">Machine Serial No.:</td>*#
<td>
#Html.TextBoxFor(x => x.Machine_serial_no, new { placeHolder = "Enter Machine Serial here.", #class = "serial1"})
#Html.ValidationMessageFor(x => x.Machine_serial_no)
</td>
<td><input type="button" value="Cancel" id="DeleteBtn1" style="color:red;" /></td>
</tr>
</table>
</div>
}
Assuming you want to alert the user as soon as they enter a non unique value, then you need to handle the .change() event of the textbox, and since the textboxes are being added dynamically, you need to use event delegation
$('#td_serial').on('change', '.serial1', function() {
var isvalid = true;
var inputs = $('.serial1').not($(this));
var text = $(this).val();
$.each(inputs, function(index, item) {
if ($(this).val() && $(this).val() === text) {
isvalid = false;
return false;
}
});
if (!isvalid) {
alert('not unique!');
}
});
Note the alert('not unique!') is just for testing purposes - its not clear how you want to notify the user - e.g. include a div with an error message that your might show/hide as required
Next your partial includes #Html.ValidationMessageFor(x => x.Machine_serial_no) suggesting you have validation attributes. In order to get client side validation for dynamically created elements you need to re-parse the validator when the new elements have been added. Modify your script to
for (i = 0; i < count; i++) {
$.ajax({
type: 'GET',
data: { mid: $('#machineTypes_MTId').val(), modelName: $('#searchid').val(), modelId: $('#searchValue').val() },
url: '#Url.Action("AddMachineSerial","Import")',
success: function (response) {
$('#ShowModel').show();
$('#td_serial').prepend(response);
$('#count').val(0);
// Reparse the validator
$('form').data('validator', null);
$.validator.unobtrusive.parse(form);
}
});
}
Side note - consider modifying this so that you only re-parse once all ajax calls are complete
Note also that you should only have one #Html.ValidationSummary(true) (your currently is adding one for each partial) and you need to remove the scripts from the partial - your should have one copy of the scripts only in the main view
I think this is you want to validate client side
$(function (){
$('#partialViewtextbox_Id').change(function (){
var partial = $('#partialViewtextbox_Id').val();
var main = $('#maintextbox_Id').val();
if(partial == main)
{
alert("value already available");
}
});
});
I can get part of the data to render to the page (specifically: request, ack, and return_info) however it will not render my user data (user_id, name, session_token, photo_url). I need all user data stored to render in a table.
$(document).ready(function () {
$.ajax({
url: "http://url/getaccount",
type: 'GET',
dataType: "json",
data: {
'account': 'all'
},
}).then(function (data) {
$('.request').append(data.request);
$('.ack').append(data.ack);
$('.return_info').append(data.return_info);
$('user_id').append(data.user_id);
$('.name').append(data.name);
$('.session_token').append(data.session_token);
$('.photo_url').append(data.photo_url);
});
console.log();
});
Html
<table class="table table-striped">
<tr>
<td><b>User</b>
</td>
<td><b>Turbo User ID</b>
</td>
<td><b>Name</b>
</td>
<td><b>Session Token<b></td>
<td><b>Request</b>
</td>
<td><b>Ack</b>
</td>
<td><b>Return Info<b></td>
</tr>
<tr>
<td class="photo_url"></td>
<td class="user_id"></td>
<td class="name"></td>
<td class="session_token"></td>
<td class="request"></td>
<td class="ack"></td>
<td class="return_info"></td>
</tr>
</table>
I will be using this for several hundred users. I am not sure if I will need a for loop of not. Thank you!
<table id="myTable" class="table table-striped">
<thead>
<tr>
<th><b>User</b></th>
<th><b>Turbo User ID</b>
</th>
<th><b>Name</b>
</th>
<th><b>Session Token<b></th>
<th><b>Request</b>
</th>
<th><b>Ack</b> </th>
<th><b>Return Info<b></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
$(document).ready(function () {
$.ajax({
url: "http://url/getaccount",
type: 'GET',
dataType: "json",
data: {
'account': 'all'
},
}).then(function (data) {
for(var i = 0; i < data.accounts.length; i++){
$('#myTable tbody').append("<tr>");
$('#myTable tbody').append("<td class=\"photo_url\">" + data.accounts[i].photo_url + "</td>");
$('#myTable tbody').append("<td class=\"user_id\">" + data.accounts[i].user_id + "</td>");
//etc...
$('#myTable tbody').append("</tr>");
}
});
console.log();
});