Not sure how to manage my data in an observableArray for updating - data-binding

I'm just starting to play around with KO as I want to bring it into an upcoming project. In my spare time I've been playing with a web service at work, this has basically been starting off with doing something with the data, then doing something else. So first I just returned a list of drug names. OK, let's add a count of the returned results. OK, let's populate the individual drug details in a modal. OK, let's edit a drug name. No real rhyme or reason, just coming up with stuff and playing around with KO.
I'm at the point where I'm not sure how to really manage my data so it gets updated everywhere. I've made a screenshot that walks you through what I have and illustrates the problem.
http://i.imgur.com/5qNWQ.jpg
Get my search results by clicking on the "y" button. I then select
the "Yasmin 28" drug
I get the detail view for that drug in a modal window
I edit the drug name and click the "save" button
The drug name is updated in the modal window
I "cheat" and update the drug name in the search results by just
crawling that part of the DOM and replacing the old drug name with
the new drug name.
Problem with this is, it isn't taking advantage of the observable nature of KO...If I were to close the modal and click on the "Yasmin 28" drug link again, the modal would show "Yasmin 28" not what I just changed it to ("something wonderful").
I'm not quite sure how to track if a property changes in my observableArray. I made two observableArrays, one holds the list of drug names for the search results, the other holds the details of the drug. I also made an observable for the current drug name.
Can someone explain what I need to do to track my drug name everywhere? I've included the code below as well as the JSON that I'm working with at the very bottom.
<div id="shell">
<button class="load" value="j">j</button>
<button class="load" value="k">k</button>
<button class="load" value="x">x</button>
<button class="load" value="y">y</button>
<button class="load" value="z">z</button>
<p id="loading"><img src="#{facesContext.externalContext.requestContextPath}/img/spinner.gif"/></p>
<h3 data-bind="visible: drugList().length > 0"><span data-bind="text: count" class="count"></span> records returned</h3>
<ul data-bind="foreach: drugList">
<li>
<span data-bind="text: drugName" class="results_drug_name"></span>
<a data-bind="click: $root.showDetails" href="#" class="show">show details</a>
</li>
</ul>
</div>
<!-- start modal: drug details -->
<div id="dialog" data-bind="jqDialog: {autoOpen: false, title: drugName}">
<p id="dialog_save_message" class="message_success">Changes saved successfully!!!!!!!!</p>
<table data-bind="foreach: drugListDetails" class="table" width="100%" cellpadding="0" cellspacing="0" border="1">
<tr>
<th scope="row">pdlId</th>
<td data-bind="text: pdlId"></td>
</tr>
<tr>
<th scope="row">drugName</th>
<td>
<span data-bind="text: $root.drugName" class="readonly"></span>
<input id="edit_drugname" class="edit_textfield" type="text" value="" size="35" />
<button data-bind="click: $root.editSave" class="edit_buttons save">Save</button>
<button data-bind="click: $root.editCancel" class="edit_buttons cancel">Cancel</button>
<ul class="detail_actions">
<li><a data-bind="click: $root.edit" href="#" class="edit">edit</a></li>
</ul>
</td>
</tr>
<tr>
<th scope="row">dosageFormDesc</th>
<td data-bind="text: dosageFormDesc"></td>
</tr>
<tr>
<th scope="row">strength</th>
<td data-bind="text: strength"></td>
</tr>
<tr>
<th scope="row">activeIngredient</th>
<td data-bind="text: activeIngredient"></td>
</tr>
<tr>
<th scope="row">tier</th>
<td data-bind="text: tier"></td>
</tr>
<tr>
<th scope="row">ancillaryCharge</th>
<td data-bind="text: ancillaryCharge"></td>
</tr>
<tr>
<th scope="row">preauthCode</th>
<td data-bind="text: preauthCode"></td>
</tr>
<tr>
<th scope="row">quantityLimit</th>
<td data-bind="text: quantityLimit"></td>
</tr>
<tr>
<th scope="row">prefAlternative</th>
<td data-bind="text: prefAlternative"></td>
</tr>
<tr>
<th scope="row">specialtyDrug</th>
<td data-bind="text: specialtyDrug"></td>
</tr>
<tr>
<th scope="row">partbCob</th>
<td data-bind="text: partbCob"></td>
</tr>
<tr>
<th scope="row">drugClassGroupId</th>
<td data-bind="text: drugClassGroupId"></td>
</tr>
<tr>
<th scope="row">drugClassId</th>
<td data-bind="text: drugClassId"></td>
</tr>
<tr>
<th scope="row">drugClass</th>
<td data-bind="text: drugClass"></td>
</tr>
<tr>
<th scope="row">genericInd</th>
<td data-bind="text: genericInd"></td>
</tr>
<tr>
<th scope="row">tip</th>
<td data-bind="text: tip"></td>
</tr>
</table>
</div>
<!-- end modal: drug details -->
<script>
$(function() {
$('.load').click(function() {
var $letter = $(this).attr('value');
//show spinner
$('#loading').show();
//load in drug list data
$.getJSON('/PreferredDrugList/service/preferredDrugs/' + $letter, function(data) {
//hide spinner
$('#loading').hide();
//replace drugList observableArray data
//preferredDrugs is an array of objects, each elem is an individual drug
myViewModel.drugList(data.preferredDrugs);
//replace count observable data
myViewModel.count(data.count);
});//end getJSON
});//end click
//setup modal dialog options
$('#dialog').dialog({
autoOpen: false,
closeOnEscape: true,
modal: true,
width:850,
height:500
});
});//end ondomready
//custom binding to initialize a jQuery UI dialog
ko.bindingHandlers.jqDialog = {
init: function(element) {
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$(element).dialog("destroy");
});
},
update: function(element, valueAccessor) {
var options = ko.toJS(valueAccessor());
if (options) {
$(element).dialog(options);
}
}
};
var myViewModel = {
count: ko.observable(), //# of records returned
drugList: ko.observableArray(), //list of drug names - an array of objects
drugListDetails: ko.observableArray(), //list of individual drug details
drugName: ko.observable(), //current drug name
//show drug details in modal
//func gets passed the current observableArray elem (the individual drug info we clicked on, this is an object)
showDetails: function(obj) {
//replace current drug name observable data
myViewModel.drugName(obj.drugName);
//replace drugListDetails observableArray data, otherwise we'll append data to the modal
myViewModel.drugListDetails([]);
//push individual drug info to details observableArray
myViewModel.drugListDetails.push(obj);
//show dialog
$('#dialog').dialog('open');
return false;
},
//edit drug from modal
edit: function(obj) {
var $edit = $('#dialog').find('td .edit'),
$currentTD = $edit.closest('td');
$currentTD.addClass('editing');
$currentTD.find('.readonly').hide();
$currentTD.find('.edit_textfield').show().select();
$currentTD.find('.edit_buttons').show();
return false;
},
//save an edit
editSave: function(obj) {
alert('TODO save back to the server');
var $saveBtn = $('#dialog').find('td .save'),
$currentTD = $saveBtn.closest('td'),
newDrugName = $('#edit_drugname').val(),
$dialog_save_message = $('#dialog_save_message');
//save new drug name to observable
myViewModel.drugName(newDrugName);
$currentTD.removeClass('editing');
$currentTD.find('.readonly').show();
$currentTD.find('.edit_textfield').hide();
$currentTD.find('.edit_buttons').hide();
$dialog_save_message.slideDown('slow', function() {
//animation complete
setTimeout(function() {
$dialog_save_message.slideUp();
}, 3000);
});
//cheat and update search results list with new drug name
$('.results_drug_name').each(function(index, elem) {
var $text = $(this).text();
if ($text === obj.drugName) {
$(this).text(newDrugName).addClass('edited');
}
});
},
//cancel an edit
editCancel: function(obj) {
var $cancelBtn = $('#dialog').find('td .cancel'),
$currentTD = $cancelBtn.closest('td');
$currentTD.removeClass('editing');
$currentTD.find('.readonly').show();
$currentTD.find('.edit_textfield').hide();
$currentTD.find('.edit_buttons').hide();
}
};
ko.applyBindings(myViewModel);
<!--what's returned from the web service-->
<pre>
{
"preferredDrugs": [(8)
{
"pdlId": 8090,
"drugName": "y-cof-dmx",
"dosageFormDesc": "Liquid",
"strength": "4MG/5ML; 15MG/5ML; 7.5MG/5ML",
"activeIngredient": "BROMPHENIRAMINE MALEATE; DEXTROMETHORPHAN HYDROBROMIDE; PHENYLEPHRINE HYDROCHLORIDE",
"tier": "OTC",
"ancillaryCharge": "NA",
"preauthCode": " ",
"quantityLimit": " ",
"prefAlternative": null,
"specialtyDrug": " ",
"partbCob": " ",
"drugClassGroupId": 74,
"drugClassId": 152,
"drugClass": "Respiratory Tract Agents » Antitussives",
"genericInd": "1",
"tip": " "
},-
{
"pdlId": 13417,
"drugName": "YASMIN 28",
"dosageFormDesc": "Tablet",
"strength": "3MG; 0.03MG",
"activeIngredient": "DROSPIRENONE; ETHINYL ESTRADIOL",
"tier": "3",
"ancillaryCharge": "AC",
"preauthCode": " ",
"quantityLimit": "28.0 tabs each 28 days",
"prefAlternative": "ethinyl estradiol/drospirenone",
"specialtyDrug": " ",
"partbCob": " ",
"drugClassGroupId": 3,
"drugClassId": 200,
"drugClass": "Hormones and Synthetic Substitutes » Contraceptives",
"genericInd": "0",
"tip": " "
},-
{
"pdlId": 24765,
"drugName": "YAZ",
"dosageFormDesc": "Tablet",
"strength": "3MG; 0.02MG",
"activeIngredient": "DROSPIRENONE; ETHINYL ESTRADIOL",
"tier": "3",
"ancillaryCharge": "AC",
"preauthCode": " ",
"quantityLimit": "28.0 tabs each 28 days",
"prefAlternative": "ethinyl estradiol/drospirenone",
"specialtyDrug": " ",
"partbCob": " ",
"drugClassGroupId": 3,
"drugClassId": 200,
"drugClass": "Hormones and Synthetic Substitutes » Contraceptives",
"genericInd": "0",
"tip": " "
},-
{
"pdlId": 2252,
"drugName": "YERVOY",
"dosageFormDesc": "Solution",
"strength": "50MG/10ML",
"activeIngredient": "IPILIMUMAB",
"tier": "NC",
"ancillaryCharge": "NA",
"preauthCode": " ",
"quantityLimit": " ",
"prefAlternative": null,
"specialtyDrug": " ",
"partbCob": " ",
"drugClassGroupId": 115,
"drugClassId": 1,
"drugClass": "Antineoplastic Agents",
"genericInd": "0",
"tip": " "
},-
{
"pdlId": 20993,
"drugName": "YERVOY",
"dosageFormDesc": "Solution",
"strength": "200MG/40ML",
"activeIngredient": "IPILIMUMAB",
"tier": "NC",
"ancillaryCharge": "NA",
"preauthCode": " ",
"quantityLimit": " ",
"prefAlternative": null,
"specialtyDrug": " ",
"partbCob": " ",
"drugClassGroupId": 115,
"drugClassId": 1,
"drugClass": "Antineoplastic Agents",
"genericInd": "0",
"tip": " "
},-
{
"pdlId": 564,
"drugName": "YF-VAX",
"dosageFormDesc": "Injection",
"strength": "0",
"activeIngredient": "YELLOW FEVER VACCINE",
"tier": "NC",
"ancillaryCharge": "NA",
"preauthCode": " ",
"quantityLimit": " ",
"prefAlternative": null,
"specialtyDrug": " ",
"partbCob": " ",
"drugClassGroupId": 79,
"drugClassId": 284,
"drugClass": "Serums, Toxoids and Vaccines » Vaccines",
"genericInd": "0",
"tip": " "
},-
{
"pdlId": 8910,
"drugName": "yodefan-nf chest congestion",
"dosageFormDesc": "Liquid",
"strength": "200MG/5ML",
"activeIngredient": "GUAIFENESIN",
"tier": "OTC",
"ancillaryCharge": "NA",
"preauthCode": " ",
"quantityLimit": " ",
"prefAlternative": null,
"specialtyDrug": " ",
"partbCob": " ",
"drugClassGroupId": 84,
"drugClassId": 155,
"drugClass": "Respiratory Tract Agents » Expectorants",
"genericInd": "1",
"tip": " "
},-
{
"pdlId": 13101,
"drugName": "YODOXIN",
"dosageFormDesc": "Tablet",
"strength": "650MG",
"activeIngredient": "IODOQUINOL",
"tier": "3",
"ancillaryCharge": "NA",
"preauthCode": " ",
"quantityLimit": " ",
"prefAlternative": "iodoquinol",
"specialtyDrug": " ",
"partbCob": " ",
"drugClassGroupId": 164,
"drugClassId": 277,
"drugClass": "Anti-infective Agents » Antiprotozoals",
"genericInd": "0",
"tip": " "
}-
],-
"count": 8
}
</pre>
</script>

First, remove the drugListDetails array as it causes confusion by holding a duplicate of your data.
Second, use ko.mapping.fromJS and ko.mapping.toJS to map your data.preferredDrugs to and from an observable array. This will allow knockout to track the changes in the GUI for every element of the array. Documentation for these can be found here.
You can also do the mapping manually if you do not want to use the mapping plugin.
Third, add a new showDetails element to each entry in your data.preferredDrugs array that defaults to false. This will be used in the next step to determine if the dialog should be shown or not. The showDetails element will need to be toggled when the existing $root.showDetails is called.
Fourth, modify the dialog div to use the drugList array and bind its visible value to the showDetails value of each drug element. This will create multiple hidden dialogs, so you may want to change the id value of each.

Related

Bootstrap - Uncaught TypeError: Cannot read property 'click' of undefined on checkbox click

I have a simple mvc table in my cshtml page where I am trying to add a checkbox in one of the columns but I am getting following error wheh I am clicking on the checkbox:
Uncaught TypeError: Cannot read property 'click' of undefined
Now this error is coming from bootstrap.js file:
b.prototype.click = function(b) {
var c = a(b.currentTarget).closest("tr").find(this.options.target)[0];
if (a(b.target)[0] !== c)
if (b.preventDefault(),
c.click)
c.click();
else if (document.createEvent) {
var d = document.createEvent("MouseEvents");
d.initMouseEvent("click", !0, !0, window, 0, 0, 0, 0, 0, !1, !1, !1, !1, 0, null),
c.dispatchEvent(d)
}
}
I can see that the value of "c" is undefined and due to that, it throws the error. If I comment bootstrap.js file from the layout page. Everything is ok.
Here is my table:
<table id="DashboardTab" class="table table-striped rowlink table-hover" data-link="row">
<tr>
<th>
Name
</th>
<th>
Groups
</th>
<th>Active</th>
<th></th>
</tr>
#{var i = 0;}
#foreach (var item in Model)
{
<tr>
<td style="display: none">#item.Id</td>
<td>
#Html.ActionLink(item.Name, "Edit", new { id = item.ID })
</td>
<td>
<i>All</i>
</td>
<td>
#if (item.IsStd)
{
#Html.CheckBox("Active" + i, item.IsActive.Value)
}
</td>
<td style="display: none">#item.IsStandard</td>
<td>
<i class="fa fa-arrows-v" aria-hidden="true"></i>
</td>
</tr>
i++;
}
</table>
What am I doing wrong?
Update:
So the issue is because of "data-link="row". Actually the row is clickable and thus, clicking on checkbox acts like a row click. How can I only make few rows clickable and not all?
So the issue was because of the data-link=row in the table. I needed only few rows to be clickable so I removed data-link=row from table and in the in added onclick() event:
if(item.IsStd){
<tr onclick="location.href = '#Url.Action( "Edit", "Home",new {id = item.ID})'">
}

How to grab the sum of a jquery datatables column to use in aspx?

I generate the code for datatables in codebehind .cs file. I have some columns with currency values. How can I sum the whole column and grab it so that I can use it in the .cs file to fill a label?
Also is it possible to grab the value only of the shown results if the searchfilter is used? E.g. something is typed in the searchfilter so rows get hide and I need the sum only of the visible rows.
Thanks
aspx:
<div id="DIV_Table" runat="server"> </div> //the content will be filled code-behind
<asp:Label ID="lbl_Sum" runat="server"></asp:Label> //Label to show the sum
cs:
//datatable dt is the source
string html = "<table id='liste' class='display' cellspacing='0' style='width:100%'><thead>";
//add header row
html += "<tr>";
for (int i = 0; i <= dt.Columns.Count - 1; i++)
{
html += "<th>" + dt.Columns[i].ColumnName + "</th>";
}
html += "</tr></thead><tbody>";
//add rows
for (int i = 0; i < dt.Rows.Count; i++)
{
html += "<tr>";
for (int y = 0; y <= dt.Columns.Count - 1; y++)
{
html += "<td>" + dt.Rows[i][y].ToString() + "</td>";
}
html += "</tr>";
}
//footer
html += "</tbody><tfoot><tr>";
foreach (DataColumn dc in dt.Columns) html += #"<th>" + dc.ColumnName + "</th>";
html += "</tr></tfoot></table>";
//javascript
html += #"<script>
$(document).ready(function() {
$('#liste').DataTable({
fixedHeader: {
header: true,
footer: true
},
order: [[ 0, 'desc' ]],
paging: false,
columnDefs: [{ type: 'currency', targets: 7 }
{ targets: 8, visible: false},],
language: { 'decimal': ',',
'thousands': '.',
'sEmptyTable': 'Keine Daten in der Tabelle vorhanden',
'sInfo': '_START_ bis _END_ von _TOTAL_ Einträgen',
'sInfoEmpty': '0 bis 0 von 0 Einträgen',
'sInfoFiltered': '(gefiltert von _MAX_ Einträgen)',
'sInfoPostFix': '',
'sInfoThousands': '.',
'sLengthMenu': '_MENU_ Einträge anzeigen',
'sLoadingRecords': 'Wird geladen...',
'sProcessing': 'Bitte warten...',
'sSearch': 'Suchen',
'sZeroRecords': 'Keine Einträge vorhanden.',
'oPaginate': {
'sFirst': 'Erste',
'sPrevious': 'Zurück',
'sNext': 'Nächste',
'sLast': 'Letzte'
},
'oAria': {
'sSortAscending': ': aktivieren, um Spalte aufsteigend zu sortieren',
'sSortDescending': ': aktivieren, um Spalte absteigend zu sortieren'
}
},
rowCallback: function(row, data, index)
{
if(data[29] == 'Abgeschlossen') { $(row).css('background-color', '#bfbfbf'); }
},
});
});
</script>";
DIV_Table.InnerHtml = html;
Will out changing to much of your current code you could adapt that .sum() datatables function you linked by running it on the datatables search.dt event, then also running it on page load for the inital value. See below (only the javascript is important to you - HTML and CSS is just for demo. Test by searching for like the letter "c" or the letter "f" to see the Total change based on the column 8 value):
var table;
$(document).ready(function() {
$.fn.dataTable.Api.register('column().data().sum()', function() {
return this.reduce(function(a, b) {
var x = parseFloat(a) || 0;
var y = parseFloat(b) || 0;
return x + y;
});
});
table = $('#liste').DataTable({
fixedHeader: {
header: true,
footer: true
},
order: [
[0, 'desc']
],
paging: false,
columnDefs: [{
type: 'currency',
targets: 7
}, {
targets: 8,
visible: false
}],
language: {
'decimal': ',',
'thousands': '.',
'sEmptyTable': 'Keine Daten in der Tabelle vorhanden',
'sInfo': '_START_ bis _END_ von _TOTAL_ Einträgen',
'sInfoEmpty': '0 bis 0 von 0 Einträgen',
'sInfoFiltered': '(gefiltert von _MAX_ Einträgen)',
'sInfoPostFix': '',
'sInfoThousands': '.',
'sLengthMenu': '_MENU_ Einträge anzeigen',
'sLoadingRecords': 'Wird geladen...',
'sProcessing': 'Bitte warten...',
'sSearch': 'Suchen',
'sZeroRecords': 'Keine Einträge vorhanden.',
'oPaginate': {
'sFirst': 'Erste',
'sPrevious': 'Zurück',
'sNext': 'Nächste',
'sLast': 'Letzte'
},
'oAria': {
'sSortAscending': ': aktivieren, um Spalte aufsteigend zu sortieren',
'sSortDescending': ': aktivieren, um Spalte absteigend zu sortieren'
}
},
rowCallback: function(row, data, index) {
if (data[29] == 'Abgeschlossen') {
$(row).css('background-color', '#bfbfbf');
}
},
})
.on('search.dt', function() {
var total = table.column(7, {
page: 'current'
}).data().sum();
$('.total-label').text(total);
});
var total = table.column(7, {
page: 'current'
}).data().sum();
$('.total-label').text(total);
});
table {
width: 100%;
border-collapse: collapse;
}
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.min.js"></script>
<h2>
Total:
<label class="total-label"></label>
</h2>
<hr>
<table id="liste">
<thead>
<tr>
<td>Column 1</td>
<td>Column 2</td>
<td>Column 3</td>
<td>Column 4</td>
<td>Column 5</td>
<td>Column 6</td>
<td>Column 7</td>
<td>Column 8</td>
<td>Column 9</td>
</tr>
</thead>
<tbody>
<tr>
<td>abc 1</td>
<td>abc 1</td>
<td>abc 1</td>
<td>abc 1</td>
<td>abc 1</td>
<td>abc 1</td>
<td>abc 1</td>
<td>1</td>
<td>hidden</td>
</tr>
<tr>
<td>cdf 2</td>
<td>cdf 2</td>
<td>cdf 2</td>
<td>cdf 2</td>
<td>cdf 2</td>
<td>cdf 2</td>
<td>cdf 2</td>
<td>2</td>
<td>hidden</td>
</tr>
<tr>
<td>fgh 3</td>
<td>fgh 3</td>
<td>fgh 3</td>
<td>fgh 3</td>
<td>fgh 3</td>
<td>fgh 3</td>
<td>fgh 3</td>
<td>3</td>
<td>hidden</td>
</tr>
</tbody>
</table>
You will also need to add the CssClass="total-label" to your <asp:Label /> or whatever class you want so you can reference it in javascript easily.

How to properly load CSS into a Chrome Extension popup.html?

What: I am creating a Chrome Extension.
Setup:
When I click the extension icon, it loads popup.html as a window. I am trying to load a JSON table of data using this code http://bootstrap-table.wenzhixin.net.cn/examples/ into a pretty HTML table.
Problem: The table loads fine. The javascript appears to be working fine but the stylesheet does not appear to be working. I linked to the local stylesheet in the head of popup.html which loads when I click the extensions's icon in Chrome like so...
<link rel="stylesheet" type="text/css" href="bootstrap-table.css">
Question: Do I need to add it to the manifest somewhere? I just need the stylesheet for the popup html. I dont need to inject it into the web page. I am just trying to display a pretty html table.
manifest.json
{
"manifest_version": 2,
"name": "Chrome Extension",
"description": "Analyze page.",
"version": "0.1",
"icons": { "32": "icon32.png",
"72": "icon72.png",
"114": "icon114.png",
"144": "icon144.png" },
"browser_action": {
"default_icon": "icon32.png",
"default_popup": "popup.html"
},
"web_accessible_resources": [
"bootstrap-table.css",
],
"permissions": [
"activeTab",
]
}
// see http://bootstrap-table.wenzhixin.net.cn/documentation/
// see http://issues.wenzhixin.net.cn/bootstrap-table/#methods/getSelections.html
var data = [
{
"name": "bootstrap-table",
"stargazers_count": "526",
"forks_count": "122",
"description": "An extended Bootstrap table with radio, checkbox, sort, pagination, and other added features. (supports twitter bootstrap v2 and v3) "
},
{
"name": "multiple-select",
"stargazers_count": "288",
"forks_count": "150",
"description": "A jQuery plugin to select multiple elements with checkboxes :)"
},
{
"name": "bootstrap-show-password",
"stargazers_count": "32",
"forks_count": "11",
"description": "Show/hide password plugin for twitter bootstrap."
},
{
"name": "blog",
"stargazers_count": "13",
"forks_count": "4",
"description": "my blog"
},
{
"name": "scutech-redmine",
"stargazers_count": "6",
"forks_count": "3",
"description": "Redmine notification tools for chrome extension."
}
];
function renderStatus(statusText) {
document.getElementById('status').textContent = statusText;
}
// MAIN CODE: on click of extension icon
document.addEventListener('DOMContentLoaded', function() {
//renderStatus('Test1');
//$('#status').append('Test2');
$(function () {
$('#table').bootstrapTable({
data: data
});
var $table = $('#table');
$('#select-button').click(function () {
var msg = 'getSelections: ' + JSON.stringify($table.bootstrapTable('getSelections'));
renderStatus(msg);
});
});
});
<!doctype html>
<html>
<head>
<title>Chrome Extension</title>
<link rel="stylesheet" type="text/css" href="bootstrap-table.css">
<style>
body{
width:820px;
height:400px;
}
#table{
width:100%;
}
</style>
<script type="text/javascript" src="jquery-3.1.1.min.js"></script>
<script type="text/javascript" src="bootstrap-table.js"></script>
<script type="text/javascript" src="popup.js"></script>
</head>
<body>
<div id="status"></div>
<div class="toolbar">
<button id="select-button" class="btn btn-default">Selected Rows</button>
<button type="button" class="btn btn-default">
<i class="glyphicon glyphicon-plus"></i>
</button>
<button type="button" class="btn btn-default">
<i class="glyphicon glyphicon-heart"></i>
</button>
<button type="button" class="btn btn-default">
<i class="glyphicon glyphicon-trash"></i>
</button>
</div>
<table
data-show-columns="true"
data-toolbar="#toolbar"
data-search="true"
data-show-refresh="true"
data-height="460"
id="table">
<thead>
<tr>
<th data-field="state" data-checkbox="true"></th>
<th data-field="name"
data-switchable="false"
data-sortable="true">
Name
</th>
<th data-field="stargazers_count"
data-sortable="true">
Stars
</th>
<th data-field="forks_count"
data-sortable="true">
Forks
</th>
<th data-field="description"
data-visible="false"
data-sortable="true">
Description
</th>
</tr>
</thead>
</table>
</body>
</html>
In my experience, referencing CSS files included in the extension from the popup does work without adding anything CSS specific to the manifest.
After modifying the manifest so it loads, your sample above does work for me, producing a well formatted table. The manifest I used:
{
"manifest_version": 2,
"name": "Chrome Extension",
"description": "Analyze page.",
"version": "0.1",
"browser_action": {
"default_popup": "popup.html"
},
"permissions": [
"activeTab"
]
}

How can I make validation behave properly?

I am using WebMatrix, asp.net and razor. I have been following these tutorials.
This page must insert values into a database, it does it prefectly at first but then when I add validation, it gives me this error "Exception Details: System.OverflowException: Value was either too large or too small for an Int32." The database used is all nvarchar except for Techid that is an int. But what I don't understand is when I comment out
Validation.Add("no", Validator.Range(9,10 ,"Contact number can not be longer or shorter than 10 digits"));
Validation.Add("num", Validator.Range(13,13,"Is number must be 13 digits"));
Validation.Add("name", Validator.Regex("^[a-zA-Z ]+$", "Invalid format for a name"))
it works quite fine.
#{
var db = Database.Open("ProjectTest");
var Name = Request.Form["name"];
var Surname = Request.Form["surname"];
var IDNumber = Request.Form["num"];
var Address = Request.Form["add"];
var ContactNumber = Request.Form["no"];
var Course = Request.Form["course"];
var TechID = Request.Form["techID"];
var grade = Request.Form["grade"];
Validation.RequireField("name", "Name is needed");
Validation.RequireField("surname", "Surname is needed");
Validation.RequireField("num", "num is needed");
Validation.RequireField("add", "add is needed");
Validation.RequireField("no", "no is needed");
Validation.RequireField("course", "course is needed");
Validation.RequireField("grade", "grade is needed");
Validation.Add("no", Validator.Range(9,10 ,"Contact number can not be longer or shoter than 10 digits"));
Validation.Add("num", Validator.Range(13,13,"Is number must be 13 digits"));
Validation.Add("name", Validator.Regex("^[a-zA-Z ]+$", "Invalid format for a name"));
if (IsPost)
{
if (Validation.IsValid())
{
var insertQuery = "INSERT INTO UserInfo (Name, Surname, IdNum, Address, ContNum, Course, Grade) VALUES (#0, #1, #2, #3 ,#4, #5, #6)";
db.Execute( insertQuery, Name, Surname, IDNumber, Address, ContactNumber, Course, grade );
}
}
else
{
ModelState.AddFormError("There are some errors with your submission");
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
Home<br>
If you are an Student that wants to register use this form.<br>
<form method="post">
<table>
<tr>
<td>Name:</td><td><input type="text" name="name"></td>
</tr>
<tr>
<td>Surname:</td><td><input type="text" name="surname"></td>
</tr>
<tr>
<td>ID Number:</td><td><input type="text" name="num"><br></td>
</tr>
<tr>
<td>Address:</td><td><input type="text" name="add"><br></td>
</tr>
<tr>
<td>Contact Number:</td><td><input type="text" name="no"><br></td>
</tr>
<tr>
<td>Course:</td><td><input type="text" name="course" value=""></td>
</tr>
<tr>
<td>Grade:</td><td><input type="text" name="grade"></td>
</tr>
<tr><td><input type="submit" value="Submit"></td>
</tr>
</table>
#Html.ValidationMessage("name")<br>
#Html.ValidationMessage("surname")<br>
#Html.ValidationMessage("num")<br>
#Html.ValidationMessage("add")<br>
#Html.ValidationMessage("no")<br>
#Html.ValidationMessage("course")<br>
#Html.ValidationMessage("grade")
</form>
<select name="courses">
<option value="1" id="test">S7</option>
<option value="2">Commerce</option>
</select>
</body>
</html>
Validator.Range will validate if a numeric value is between minimum and maximum. Looks like you want to validate the length of the input, so you should use Validator.StringLength().

Databind elements based on select value with KnockoutJS

I want to do some clever binding on my nested KO array and I am really not sure how I would do it. Based on selection from the select, I want to get some elements based on the selection that has been made.
My ko obeservablearray, which looks like:
{
"ProductName": "Product123",
"RequiredComponents": "CAP 10% H/Vol",
"StockCode": "142111411",
"RequiredQtyByBom": 4,
"QtyUnassignedInWarehouse": 0,
"QtyAllocatedInWarehouse": 40,
"PCBReference": "442C",
"QtyOnOrder": 26,
"Vendors": [],
"RequireVendor": false
},
{
"ProductName": "Product123",
"RequiredComponents": "Screws",
"StockCode": "Screws",
"RequiredQtyByBom": 1,
"QtyUnassignedInWarehouse": 0,
"QtyAllocatedInWarehouse": 14,
"PCBReference": "Screws",
"QtyOnOrder": 26,
"Vendors": [
{"VendorID": "3",
"VendorName": "ABC Supplier",
"VendorMOQ": 50000,
"VendorItemPrice": 322},
{"VendorID": "4",
"VendorName": "DEF Supplier",
"VendorMOQ": 4,
"VendorItemPrice": 120}
],
"RequireVendor": true
},
{
"ProductName": "Product123",
"RequiredComponents": "14141415",
"StockCode": "151555231",
"RequiredQtyByBom": 1,
"QtyUnassignedInWarehouse": 0,
"QtyAllocatedInWarehouse": 170,
"PCBReference": "1414",
"QtyOnOrder": 26,
"Vendors": [],
"RequireVendor": false
}
I want to data-bind the Vendor MOQ, Price based on what vendor was selected. I pass the selectedVendorID back to my viewmodel.
<select data-bind="options: Vendors, optionsText: 'VendorName', optionsCaption: 'Choose a Vendor...', value: SelectedVendor" class="form-control"></select>
I want my Output to look like the following:
<table class="table table-bordered">
<thead>
<tr>
<td>Stock Code</td>
<td>Qty</td>
<td>Vendor</td>
<td>Price p/Unit</td>
<td>MOQ</td>
<td>Value</td>
</tr>
</thead>
<tbody data-bind="foreach: CheckStock">
<tr>
<td data-bind="text: StockCode"></td>
<td data-bind=""></td>
<td>
<select data-bind="options: Vendors, optionsText: 'VendorName', optionsCaption: 'Choose a Vendor...', value: SelectedVendor" class="form-control"></select>
</td>
<td>
<input type="text" data-bind="value: Vendors().VendorPrice" /></td>
<td data-bind="text: Vendors().VendorMOQ"></td>
<td>TODO CALC</td>
</tr>
</tbody>
</table>
I have found the Solution to my Problem:
By Data binding the SelectedVendor in the Following manner I get the result I was looking for:
<input type="text" data-bind="value: SelectedVendor() ? SelectedVendor().VendorPrice : '0'" /></td>
<td data-bind="text: SelectedVendor() ? SelectedVendor().VendorMOQ : '0'"></td>
As mentioned in this Article (Example 3)

Resources