Only the first row row is required field - Dynamic table Knockout.js - javascript

<table style="margin-left:20px" border="0" class="ledgergrid" width="" cellpadding="1" cellspacing="2">
<tbody>
<tr>
<th> </th>
<th>A. Citation</th>
<th>B. Relevant Finding(s)</th>
<th>C. Overlap of Populations and/or Settings</th>
</tr>
<tbody data-bind="foreach: listCitations">
<tr style="background-color:#eeeeee;" >
<td width="1%">
<button type="button" class="btn-xs" id="delete" data-bind="click: $parent.removeCitation.bind($data), attr: { title: $parent.deleteCitationToolTip }, visible: $parent.lastIndexCitations() > 2"> X </button>
<td width="33%" ><textarea name="citation" class="" style="width:80% !important; height:60px;" data-bind="css: $parent.KCitationCSS, attr: {id: 'citation' + ($index() + 1), title: $parent.citationToolTip}, value: $data.KCitation"></textarea></td>
<td width="33%"><textarea name="relevantFindings" class="" style="width:80% !important; height:60px;" data-bind=" css: $parent.relevantFindingsCSS, attr: {id: 'relevantFindings' + ($index() + 1), title: $parent.relevantFindingsToolTip}, value: $data.KRelevantFindings"></textarea></td>
<td width="33%"><textarea name="overlapofPopulations" class="" style="width:80% !important; height:60px;" data-bind=" css: $parent.overlapofPopulationsCSS, attr: {id: 'overlapofPopulations' + ($index() + 1), title: $parent.overlapofPopulationsToolTip}, value: $data.KOverlapofPopulations"></textarea></td>
</tr>
</tbody>
</table>
I have displayed 4 rows in default case, but all of them showed as required. I would like to have only the first row required, and the rest are not required. FYI all the table is dynamic! Thanks in advance!

Do you mean to say first column after the button? From the code shared, I can see only 1 row. Am assuming that its 1st column (A. Citation) thats required and needs special look & feel. If yes, here is CSS code:
.ledgergrid td:nth-child(2) {
background-color:red;
}

Related

Bootstrap 4 - DataTable search not working on rows added by jQuery

I have a problem with the Bootstrap 4 search tool. If the rows are added manually in tbody the search works, but if I add a new row from jQuery then search doesn't see those rows.
This is the body of the table.
Below is the function that adds a new row to the table:
function addProduct(name, id, price, quantity = 1)
{
var template = $("#product-template").clone(true, true);
var existingRow = $("#product-table").find('#product' + id);
template.removeClass("disabled");
if (existingRow.length > 0)
{
var quantity = parseInt(existingRow.find('.prod-quantity').text()) + 1;
existingRow.find('.prod-quantity').text(quantity);
calculateTotalPrice(id);
return;
}
template.attr("unit-price", price);
template.attr("id", "product" + id);
template.find('.prod-name').attr("title", name);
template.attr("productID", id);
template.find('.prod-name').text(name);
template.find('.prod-quantity').text(quantity);
template.find('.total-price').text(price);
$(template).css("display", "table-row");
$("#product-table").append(template);
calculateTotalPrice(id);
orderTableData();
calculateTotalPayment();
}
<tbody id="product-table" class="prd">
<tr id="product-template" class="tr-prod disabled">
<td class="text-center nr-order" id=""></td>
<td class="prod-name" contenteditable="true" title="" style="background-color: white; color:black;">a</td>
<td class="prod-quantity text-center" contenteditable="true" style="background-color: white; color:black">1</td>
<td class="total-price text-center"></td>
<td class="col-sm-3 text-center " style="width: 25px!important;">
<i class="fas fa-minus-circle remove" title="Elimină" style="font-size:20px;color:#F08080;width:20px">
</i>
</td>
</tr>
<tr id="product-template-1" class="tr-prod disabled">
<td class="text-center nr-order" id=""></td>
<td class="prod-name" contenteditable="true" title="" style="background-color: white; color:black;">b</td>
<td class="prod-quantity text-center" contenteditable="true" style="background-color: white; color:black">1</td>
<td class="total-price text-center"></td>
<td class="col-sm-3 text-center " style="width: 25px!important;">
<i class="fas fa-minus-circle remove" title="Elimină" style="font-size:20px;color:#F08080;width:20px">
</i>
</td>
</tr>
</tbody>
I don't know why, but the rows added with the addProduct() function don't appear in the search, and not only that, but they disappear completely when I'm searching for something.
What am I missing, maybe I should update the table after I add a new row?
<script>
$(document).ready(function () {
var table = $('#product-table').DataTable();
$('.dataTables_length').addClass('bs-select');
function addProduct(name, id, price, quantity = 1)
//instead $("#product-table").append(template)
table.row.add([
'td 1',
'td 2',
'td 3',
...
'td n',
])
table.draw();
}
});
</script>

Checkboxes don't stay checked after pagination

Whenever I check a checkbox on a listing page, save it then go to page eg 2 (using pagination) and check something there and save it the checkbox on my first page is unchecked. I thought about using AJAX to save checked checkboxes to grails session but don't know how to do that - I'm beginner with JS and using views. Could someone help me out?
Here is the part with listing all companies and checkboxes in my gsp:
<g:form name="company-list-form" action="listCompany">
<div>
<g:textField id="search-field" name="query" value="${params.query}"/>
<span>
<g:checkBox id="only-blockades-box" name="onlyBlockades" class="submit-on-change" value="${params.onlyBlockades}" title="Pokaż tylko blokady"/>
<label for="only-blockades-box">Tylko blokady</label>
</span>
<g:actionSubmit value="${message(code: 'default.buttons.search', default: 'Szukaj')}" action="listCompany" class="button_orange"/>
<g:link action="listCompany" class="button_gray"><g:message code="default.buttons.clean" default="Wyczyść"/></g:link>
</div>
<div class="padding-top">
<table class="table_td company-list-table">
<tbody>
<tr class="gray2">
<th class="first">Id</th>
<th style="max-width: 100px;">Nazwa</th>
<th>Id Kontrahenta</th>
<th title="Dostęp do TPO">TPO</th>
<th style="width: 20px;" title="Dostawa bezpośrednio do magazynu">Dostawa bezpośrednio</th>
<th style="width: 20px;" title="Możliwość potwierdzania zamówień">Potwierdzanie zamówień</th>
<th style="width: 20px;" title="Możliwość importowania awizacji z XLS">Import z Excel</th>
<th style="width: 20px;" title="Możliwość awizowania zamówionych indeksów">Awizacja zam. indeksów</th>
<th style="width: 20px;" title="Możliwość awizowania tygodniowego">Awizacja tyg.</th>
<th style="width: 20px;" title="Dostęp jedynie do awizowania tygodniowego">Tylko awizacja tyg.</th>
<th title="Limit AGD przypadający na każdą kratkę okna prywatnego">AGD</th>
<th title="Limit rowerów przypadający na każdą kratkę okna prywatnego">Rowery</th>
<th>Blokady</th>
<th class="is-blocked-th">Zablokowany?</th>
</tr>
<g:each in="${companyInstanceList}" var="company" status="i">
<tr class="${(i % 2) == 0 ? 'even' : 'odd'} table_td_gray2 ${i + 1 == companyInstanceList?.size() ? 'last' : ''}">
<td class="first" style="text-decoration: underline;">
<g:link action="editCompany" id="${company?.id}">${company?.id}</g:link>
</td>
<td>
${company?.name}
</td>
<td>
${company?.idKontrahenta}
</td>
<td>
<g:checkBox name="tpoAccess.${company?.id}" id="tpo-access-${company?.id}"
checked="${company?.tpoAccess}"/>
</td>
<td>
<g:checkBox name="directDeliveryAvailable.${company?.id}"
id="direct-delivery-available-${company?.id}"
checked="${company?.directDeliveryAvailable}"/>
</td>
<td>
<g:checkBox name="accessToOrderConfirmation.${company?.id}"
id="access-to-order-confirmation-${company?.id}"
checked="${company?.accessToOrderConfirmation}"/>
</td>
<td>
<g:checkBox name="accessToXlsImport.${company?.id}"
id="access-to-xls-import-${company?.id}"
checked="${company?.accessToXlsImport}"/>
</td>
<td>
<g:checkBox name="accessToOrderedProductsAvisation.${company?.id}"
id="access-to-ordered-products-confirmation-${company?.id}"
checked="${company?.accessToOrderedProductsAvisation}"/>
</td>
<td>
<g:checkBox name="accessToLimitedAvisation.${company?.id}"
id="access-to-limited-avisation-${company?.id}"
checked="${company?.accessToLimitedAvisation}"/>
</td>
<td>
<g:checkBox name="accessOnlyToLimitedAvisation.${company?.id}"
id="access-only-to-limited-avisation-${company?.id}"
checked="${company?.accessOnlyToLimitedAvisation}"/>
</td>
<td>
<input type="text" name="agdPrivateWindowLimit.${company?.id}"
value="${company?.agdPrivateWindowLimit}"
class="shortText" id="agd-private-window-limit-${company?.id}"
onchange="validateLimits('agdPrivateWindowLimit.${company?.id}')">
</td>
<td>
<input type="text" name="bicyclePrivateWindowLimit.${company?.id}"
value="${company?.bicyclePrivateWindowLimit}"
class="shortText" id="bicycle-private-window-limit-${company?.id}"
onchange="validateLimits('bicyclePrivateWindowLimit.${company.id}')">
</td>
<td>
<g:link class="button_gray" controller="productGroup" action="list" params="[companyId: company?.id, query: params.query ?: '']">
Blokady
</g:link>
</td>
<td>
<g:if test="${company?.findBlockades()}">
<span title="Dostawca ma aktywne blokady grup towarowych." class="bold large">
✓
</span>
</g:if>
</td>
</tr>
</g:each>
</tbody>
</table>
</div>
<div class="paginateButtons">
<g:paginate controller="company" action="listCompany" total="${companyInstanceTotal}"
params="[query: params.query ?: '']"/>
</div>
<div style="float:right;">
<g:link action="createCompany" class="button_orange">
<g:message code="default.button.create.label" default="Utwórz"/>
</g:link>
<g:actionSubmit action="updateCompanies" name="companyListSubmit" class="button_orange" value="Zapisz"/>
</div>
</g:form>
Here is my javascript file associated with that view:
function validateLimits(name) {
document.getElementsByName(name)[0].value = document.getElementsByName(name)[0].value.replace(/[A-Za-z!##$%^&*" "]/g, "");
var quantity = document.getElementsByName(name)[0].value;
var toBeAvised = 9999;
if (quantity.indexOf(',') > -1 || quantity.indexOf('.') > -1 || /*quantity == "" ||*/ isNaN(quantity)) {
alert("Limit musi być liczbą całkowitą");
document.getElementsByName(name)[0].value = '';
} else if (parseInt(quantity) > toBeAvised) {
alert("Podana liczba jest większa niż maksymalny limit równy " +toBeAvised + ".");
document.getElementsByName(name)[0].value = '';
} else if (parseInt(quantity) < 0) {
alert("Limit musi być liczbą dodatnią!");
document.getElementsByName(name)[0].value = '';
}
}
And here is controller method (listCompany):
def listCompany(Integer max) {
Person person = Person.read(springSecurityService.principal.id)
Company comp = person?.company
params.max = Math.min(max ?: 25, 100)
params.offset = params.offset ?: 0
params.readOnly = true
String q = (params.query as String)?.toLowerCase() ?: ""
def query = Company.where {
id != comp?.id
name =~ "%$q%" || idKontrahenta as String =~ "%$q%"
if (params.onlyBlockades == "on") {
id in ProductGroupBlockade.findAllByCompanyIsNotNullAndEnabled(true)*.companyId
}
}
List<Company> companyInstanceList = query.list([max: params.int("max"), offset: params.int("offset"), sort: "name"])
Integer count = query.count()
if (flash.message) {
params.errors = flash.message
}
[companyInstanceList: companyInstanceList, companyInstanceTotal: count, companySaved: params.companySaved, errors: params.errors]
}
How I could fix that so my checkboxes stay checked after saving? Right now they become unchecked whenever I go to next page and save some checkboxes there.
I tend to use DataTables for situations like this but it depends on the amount of data you're dealing with to how you go about it.
If you have a relatively small data set, say 1000 rows or fewer you can use a plain DataTable, if you have more than this then you may want to use a server side processing DataTable.
Using a DataTable you would do away with all the Grails pagination, give your table an ID and just create the table in javascript like:
<script type="text/javascript">
$(document).ready( function() {
$( '#companyListTable' ).DataTable();
} );
</script>
All the pagination is handled in javascript and check boxes are preserved when navigating through the table pagination.
The reason is that you need to build your own search parameters to be sent with pagination:
<g:paginate total="${instanceTotal}" params="${search}" />
a similar post can be found here with more details of how you build this search params included as links as a form of comment within it.
Edited to add if you wantd to actually ammend pagination yourself by checking additional stuff through jquery i.e.
var something = $('#somFIeld').val()
and adding something through javascript to current pagination instead then take a read of this answer

Differentiating current textbox value from old one and showing in Angular JS

My code is like this
<body>
<div>
<table ng-app='myApp' ng-controller="MainCtrl">
<thead></thead>
<tbody ng-repeat="prdElement in palletElement track by $index">
<tr>
<td>{{prdElement.name}}</td>
</tr>
<tr ng-repeat="data in prdElement.Data">
<td>{{data.itemId}}</td>
<td>{{data.shipmentId}}</td>
<td>{{data.itemCode}}</td>
<td>{{data.description}}</td>
<td>{{data.handlingUnit}}</td>
<td>{{data.weight}}</td>
<td>{{data.class}}</td>
<td>{{data.lenght}}</td>
<td>{{data.width}}</td>
<td>{{data.height}}</td>
<td>{{data.flag}}</td>
<td>
<input type="text" ng-model="data.quantity" placeholder=" Code" required />
</td>
</tr>
<tr>
<td>
<button ng-click="newPalletItem( prdElement,$event)">Submit</button>
</td>
</tr>
<!--<tr id="displayitems" >
<td>
{{palletElement}}
</td>
</tr>-->
</tbody>
</table>
</div>
(function () {
angular.module('myApp', []).controller('MainCtrl', function ($scope) {
var counter = 0;
$scope.palletElement = [{
name: 'Pallet 1',
Data: [{
name: 'item 1',
itemId: '284307',
shipmentId: 'eb44f690-c97a-40e3-be2a-0449559e171a',
itemCode: '',
description: 'Bicycle parts - frame',
quantity: '31',
handlingUnit: 'CTN',
weight: '613.04',
class: '',
lenght: '102',
width: '42',
height: '61',
flag: 'P'
}, {
name: 'item 2',
itemId: '284308',
shipmentId: 'eb44f690-c97a-40e3-be2a-0449559e171a',
itemCode: '',
description: 'Bicycle parts - fork',
quantity: '22',
handlingUnit: 'CTN',
weight: '242.99',
class: '',
lenght: '75',
width: '34',
height: '18',
flag: 'P'
}]
}]
$scope.newPalletItem = function (palletElement, $event) {
counter++;
$scope.palletElement.push(palletElement);
}
});
}());
When some one changes the value in last column textbox and press submit button I want to calculate [preloded value in textbox - (minus) current value in that text box ] and show it in next row. So far I have managed to duplicate the entire data completely to next row. but have no Idea in how to achieve rest. Can any one pint out a solution.
Fiddle
More details from Fiddle: as you can see current value is first text box is 31 if some one changes it to 10 when I duplicate the row to bottom I want that new textbox value to be shown as 21 (which is 31-10).
Please see here: http://jsfiddle.net/8r8cxcup/
newPalletImte:
$scope.newPalletItem = function (palletElement, $event) {
var npalletElement = {};
angular.copy(palletElement, npalletElement);
counter++;
angular.forEach(npalletElement.Data, function (row) {
if (row.quantity != row.newquantity) {
row.quantity = row.quantity - row.newquantity;
}
});
$scope.palletElement.push(npalletElement);
};
});
HTML:
<table ng-app='myApp' ng-controller="MainCtrl">
<thead></thead>
<tbody ng-repeat="prdElement in palletElement track by $index">
<tr>
<td>{{prdElement.name}}</td>
</tr>
<tr ng-repeat="data in prdElement.Data" ng-init="data.newquantity = data.quantity">
<td>{{data.itemId}}</td>
<td>{{data.shipmentId}}</td>
<td>{{data.itemCode}}</td>
<td>{{data.description}}</td>
<td>{{data.handlingUnit}}</td>
<td>{{data.weight}}</td>
<td>{{data.class}}</td>
<td>{{data.lenght}}</td>
<td>{{data.width}}</td>
<td>{{data.height}}</td>
<td>{{data.flag}}</td>
<td>
<input type="text" ng-model="data.newquantity" placeholder=" Code" required />
</td>
</tr>
<tr>
<td>
<button ng-click="newPalletItem( prdElement,$event)">Submit</button>
</td>
</tr>
<!--<tr id="displayitems">
<td>
{{palletElement}}
</td>
</tr>-->
</tbody>
</table>

how to add a value from text box to a table in javascript or jquery?

I have two text_fields and a table with three column. By clicking the button, i want that two text_field value added to the tables in the first two columns. So, the user can change the text_field values again and again and the values added to the next row by clicking the add button.
The two text_fields are as follows:
<input class="cross-reference-question-value" type="text" style="border: 1px solid gray; ">
<input class="cross-reference-answer-value" type="text" style="border: 1px solid gray; ">
Here is the table
<table class="gridView" id="selected_units">
<thead>
<tr class="gridViewHeader">
<th>Question</th>
<th>Answer</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr class="<%= cycle('gridViewclickableRowDialog', 'gridViewAltclickableRowDialog') %>">
<td></td>
<td></td>
<td>Delete</td>
</tr>
</tbody>
</table>
The button_link is
<a href="#" , class="button" >hello</a>
Thanks!!
Try starting with this:
​$('.button').click(function() {
var question = $('.cross-reference-question-value').val();
var answer = $('.cross-reference-answer-value').val();
var newrow = '<tr><td>' + question + '</td><td>' + answer + '</td></tr>';
$('#selected_units tr:last').after(newrow);
});​​​​​
Check the DEMO. Add checks for empty inputs, duplicate rows, etc.

Knockout js template, filter first element of observable array

Hi I'm trying to make the first element of my observableArray hidden, the following doesn't appear to be working, any ideas?
data-bind="ifnot: $root.typedData[0]===$data"
http://jsfiddle.net/Lx8jR/
<table border="1" style="width:90%">
<tr>
<td data-bind="text: typedData()[0].name"></td>
<td data-bind="text: typedData()[0].type"></td>
</tr>
<tr>
<td>
<table data-bind="foreach: typedData()">
<tr>
<td data-bind="text: name"></td>
</tr>
</table>
</td>
<td>
<table data-bind="foreach: typedData()">
<tr data-bind="ifnot: $root.typedData[0]===$data">
<td data-bind="text: type">
</td>
<td data-bind="text: $index">
</td>
</tr>
</table>
</td>
</tr>
</table>
var ViewModel = function() {
var self = this;
this.typedData = ko.observableArray([
{ name: "Bungle", type: "Bear" },
{ name: "George", type: "Hippo" },
{ name: "Zippy", type: "Unknown" }
]).indexed();
}
Looks like you missed a () on that line.
ifnot: $root.typedData[0]===$data
becomes
ifnot: $root.typedData()[0]===$data
http://jsfiddle.net/Lx8jR/1/
A simple mistake I've made a few dozen times.
If you get into the habit of using ko.utils.unwrapObservable this becomes less of an issue. If you use that function on a non-observable, it still succeeds.
... ko.utils.unwrapObservable($root.typedData)[0]
And for reference, there's an article on KnockMeOut which suggests a few other standards that help simplify our templates and bindings.
typedData is an observableArray, so in your comparison you would want to do (add ()):
$root.typedData()[0] === $data

Categories

Resources