How sum column values and format cell using conditional formatting? - reactjs

I started to develop in React.js, and I'm using React-Bootstrap-Table.
I need to get the sum of the total of a particular column (updates on every change in search field).
I also want to add custom CSS for conditional formatting based on value (example, if amount is less than average, need to be green
text if amount is near average yellow, if amount is above
average but less than maximum orange else red).
Also number field needs to be right aligned
Code can be viewed here
var DataTable = ReactDataComponents.DataTable;
// Generate random data
var names = ['201801003', '201801002', '201801004', '201801005', '201801006'];
var cities = ['2018', '2017', '2017', '2017', '2017', '2017'];
var addresses = ['Travancore', 'Sivagangai', 'Pudhukottai', 'Madurai'];
var states = ['1200', '350', '6400', '1700', '750'];
var data = [];
for (var i = 0; i < 1000; i++) {
data.push({
id: i,
name: names[~~(Math.random() * names.length)],
city: cities[~~(Math.random() * cities.length)],
address: addresses[~~(Math.random() * addresses.length)],
state: states[~~(Math.random() * states.length)]
});
}
var columns = [{
title: 'CID',
prop: 'name'
}, {
title: 'Area',
prop: 'city'
}, {
title: 'Authority',
prop: 'address'
}, {
title: 'Amount',
prop: 'state'
}];
ReactDOM.render(React.createElement(DataTable, {
className: 'container',
keys: 'id',
columns: columns,
initialData: data,
initialPageLength: 5,
initialSortBy: {
prop: 'city',
order: 'descending'
},
pageLengthOptions: [5, 20, 50]
}), document.getElementById("root"));
<title>React Table</title>
<link rel='stylesheet prefetch' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/css/bootstrap.min.css'>
<link rel='stylesheet prefetch' href='https://cdn.rawgit.com/carlosrocha/react-data-components/v1.0.0/css/table-twbs.css'>
<link rel='stylesheet prefetch' href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.min.css'>
<body>
<br>
<h3> Area</H3>
<br>
<div id="root"></div><br>
<h3> Sum</H3>
<br>
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://npmcdn.com/react-data-components#1.0.1/dist/react-data-components.min.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/css/bootstrap.min.css'></script>
</body>
Thank you

For every row you make, add it to a counter in your state
Do conditional css based on the value in the counter
Align it to the right with css

Related

How to use yandex.metrica ecommerce layer with react&

I added a yandex.metrica script (w ecommerce layer) in my index.html
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();
for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(id, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true,
ecommerce: "dataLayer"
});
</script>
<!-- /Yandex.Metrika counter -->
I need to send some data-objects to ecommerce layer like this dataLayer.push({ ecommerce: "someData" }), but i dont understand how to do it correctly inside a react component...
it should work just like other events for YM
window.ym(yaCounterId, "reachGoal", eventName)
window.dataLayer.push({
ecommerce: {
currencyCode: 'RUB',
add: {
products: [
{
id: '43521',
name: 'Yandex bag',
price: 654.32,
brand: 'Yandex / Яndex',
category: 'Accessories/Bags',
quantity: 1,
},
],
},
},
});
just create wrapper function to make it look better

How do you toggle a checkbox on a Kendo UI PanelBar that can expand or collapse?

I am trying to make a panel bar with several expandable options with checkboxes at each level. The problem I am running into is that if you click on a checkbox that is part of an expandable panel, the checkbox does not toggle. Below is a simplified example that shows the problem. In the example below it is impossible to toggle the checkbox for Main 1
const panelBarTemplate = `
<span class='k-state-default'>
<span>#: item.text #</span>
<input type='checkbox'
id=#: item.id #
class='k-checkbox'
# if (item.isVisible) { #checked='checked'# } # />
# var ItemCheckboxLabelClass = "k-checkbox-label" #
# if (item.items) { ItemCheckboxLabelClass = "k-checkbox-label expandable-item" } #
<label class="#: ItemCheckboxLabelClass #" for=#: item.id # />
</span>
`;
var canExpandCollapse = true;
$('#side-bar-panel').kendoPanelBar({
template: panelBarTemplate,
dataSource: [{
text: 'Main 1',
id: 'Main1',
isVisible: true,
expanded: true,
items: [{
text: 'Sub 1',
id: 'Sub1',
isVisible: true
}, {
text: 'Sub 2',
id: 'Sub2',
isVisible: false
}]
}],
dataBound: function() {
$('.expandable-item').click(function() {
canExpandCollapse = false;
});
},
expand: cancelExpandCollapse,
collapse: cancelExpandCollapse
});
function cancelExpandCollapse(e) {
if (!canExpandCollapse) {
e.preventDefault();
canExpandCollapse = true;
}
}
<link href="https://kendo.cdn.telerik.com/2017.2.621/styles/kendo.common.min.css" rel="stylesheet" />
<link href="https://kendo.cdn.telerik.com/2017.2.621/styles/kendo.flat.min.css" rel="stylesheet" />
<script src="https://kendo.cdn.telerik.com/2017.2.621/js/jquery.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2017.2.621/js/kendo.all.min.js"></script>
<ul id="side-bar-panel">
</ul>
I found a solution for preventing expanding and collapsing when clicking on the checkbox here https://stackoverflow.com/a/31879672/4708150, but even though expanding and collapsing is disabled, the checkbox is still not being toggled.
I was able to find a workaround by just not using a checkbox. Instead of checkboxes I used a Kendo mobile switch and was able to get the switch to toggle and the panel bar not expand or collapse.
Below is the modified snippet. Items that changed are the panelBarTemplate, the functions inside of the dataBound configuration, and the css files for Kendo mobile were added.
const panelBarTemplate = `
<div>
<span>#: item.text #</span>
<input type='checkbox'
id=#: item.id #
# var ItemCheckboxClass = "my-checkbox" #
# if (item.items) { ItemCheckboxClass = "my-checkbox expandable-item" } #
class="#= ItemCheckboxClass #"
# if (item.isVisible) { #checked='checked'# } # />
</div>
`;
var canExpandCollapse = true;
$('#side-bar-panel').kendoPanelBar({
template: panelBarTemplate,
dataSource: [{
text: 'Main 1',
id: 'Main1',
isVisible: true,
expanded: true,
items: [{
text: 'Sub 1',
id: 'Sub1',
isVisible: true
}, {
text: 'Sub 2',
id: 'Sub2',
isVisible: false
}]
}],
dataBound: function() {
//initialize mobile switch if not already initialized.
$('.my-checkbox').each(function(index, item) {
let mobileSwitch = $(item);
let mobileSwitchData = mobileSwitch.data('kendoMobileSwitch');
if (!mobileSwitchData) {
mobileSwitch.kendoMobileSwitch();
}
});
//disable expanding and collapsing when clicking on a mobile switch
//that is attached to an expandable panel.
$('.expandable-item').siblings('.k-switch-container').click(function() {
canExpandCollapse = false;
});
},
expand: cancelExpandCollapse,
collapse: cancelExpandCollapse
});
function cancelExpandCollapse(e) {
if (!canExpandCollapse) {
e.preventDefault();
canExpandCollapse = true;
}
}
<link href="https://kendo.cdn.telerik.com/2017.2.621/styles/kendo.common.min.css" rel="stylesheet" />
<link href="https://kendo.cdn.telerik.com/2017.2.621/styles/kendo.mobile.all.min.css" rel="stylesheet" />
<link href="https://kendo.cdn.telerik.com/2017.2.621/styles/kendo.flat.min.css" rel="stylesheet" />
<link href="https://kendo.cdn.telerik.com/2017.2.621/styles/kendo.flat.mobile.min.css" rel="stylesheet" />
<script src="https://kendo.cdn.telerik.com/2017.2.621/js/jquery.min.js"></script>
<script src="https://kendo.cdn.telerik.com/2017.2.621/js/kendo.all.min.js"></script>
<ul id="side-bar-panel">
</ul>

Kendo Datasource CRUD with templates

I am using KendoUI and angular to implement a very similar scenario as in this example from Telerik website.
http://dojo.telerik.com/AreTa/2
This is what I have
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Kendo UI Snippet</title>
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2016.2.714/styles/kendo.common.min.css"/>
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2016.2.714/styles/kendo.rtl.min.css"/>
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2016.2.714/styles/kendo.silver.min.css"/>
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2016.2.714/styles/kendo.mobile.all.min.css"/>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2016.2.714/js/kendo.all.min.js"></script>
</head>
<body>
<style>html { font: 12px sans-serif; }</style>
<div id="grid"></div>
<script>
var sampleData = [
{ProductName: "Sample Name", Description: "Sample Description"}
];
// custom logic start
var sampleDataNextID = sampleData.length + 1;
function getIndexByName(name) {
var idx,
l = sampleData.length;
for (var j=0; j < l; j++) {
if (sampleData[j].getIndexById == name) {
return j;
}
}
return null;
}
// custom logic end
$(document).ready(function () {
var dataSource = new kendo.data.DataSource({
transport: {
read: function (e) {
// on success
e.success(sampleData);
// on failure
//e.error("XHR response", "status code", "error message");
},
create: function (e) {
// assign an ID to the new item
//e.data.ProductName = e.data;
// save data item to the original datasource
sampleData.push(e.data);
// on success
e.success(e.data);
// on failure
//e.error("XHR response", "status code", "error message");
},
update: function (e) {
// locate item in original datasource and update it
sampleData[getIndexByName(e.data.ProductName)] = e.data;
// on success
e.success();
// on failure
//e.error("XHR response", "status code", "error message");
},
destroy: function (e) {
// locate item in original datasource and remove it
sampleData.splice(getIndexByName(e.data.ProductName), 1);
alert("Delete Success"+e.data.ProductName) ;
// on success
e.success();
// on failure
//e.error("XHR response", "status code", "error message");
}
},
error: function (e) {
// handle data operation error
alert("Status: " + e.status + "; Error message: " + e.errorThrown);
},
pageSize: 10,
batch: false,
schema: {
model: {
id: "ProductName",
fields: {
ProductName: { validation: { required: true } },
Description: { type: "text"}
}
}
}
});
$("#grid").kendoGrid({
dataSource: dataSource,
pageable: true,
toolbar: ["create"],
columns: [
{ field: "ProductName", title: "Mobile Phone" },
{ field: "Description", width: "120px" },
{ command: ["destroy"], title: "Action;", width: "200px" }
],
editable: "inline"
});
});
</script>
</body>
</html>
And it works, the way it is on Telerik website
The change I want to do is that upon "create", I want the ProductName field be a drop down, instead of textfield, populated with values I have in another json (not sampleData). That has a value (productName) and Description - description
Also, the Description field is not to be typeable, but rather "obtained" from the description of the selected in dropdown.
Can anyone help ?
Use a custom editor for the ProductName field:
http://docs.telerik.com/kendo-ui/api/javascript/ui/grid#configuration-columns.editor
http://demos.telerik.com/kendo-ui/grid/editing-custom
Attach a change handler to the DropDownList and set() the corresponding value to the Description field of the data item (which is a Kendo UI Model instance that you already have from the editor function's arguments).
http://docs.telerik.com/kendo-ui/api/javascript/ui/dropdownlist#events-change
http://docs.telerik.com/kendo-ui/api/javascript/data/observableobject#methods-set
You will also need to prevent direct editing of the Description field. This can be easily achieved if you use a custom "editor" for this field, which simply outputs the current value in a <span> element.

Pass array of object properties to filter

I have a custom angular filter that I'm trying to make more generic. The filter looks a collection of employees and filters down the list based on the number of months that have passed since they were hired. I'm trying to make the filter more generic so I can use it on other lists that have dates but will have a different property name (for example: filter invoices that have been created in the last xx months). How can I pass in the name of the property I want to filter on, or how do I pass in the collection of just the date property instead of the whole object?
html
<html ng-app="dateFilterTest">
<head>
</head>
<body ng-controller="filterController">
<select ng-model="maxLookBack">
<option value="6">6 Months</option>
<option value="12" selected="selected">1 Year</option>
<option value="24">2 Year</option>
<option value="999">All</option>
</select>
<ul>
<li ng-repeat="person in people | DateAgeFilter:maxLookBack">{{person.name}}</li>
</ul>
</body>
<script type="text/javascript" src="js/angular.min.js"></script>
<script type="text/javascript" src="js/controllers/dateFiltercontroller.js"></script>
</html>
js
var app = angular.module('dateFilterTest', []);
app.filter('DateAgeFilter', function(){
return function(items, maxage) {
var minDate = new Date()
minDate.setMonth(minDate.getMonth() - maxage);
var result = [];
for (var i=0; i<items.length; i++) {
if (items[i].hireDate.getTime() > minDate.getTime()) {
result.push(items[i]);
}
}
return result;
};
});
app.controller('filterController', function($scope){
$scope.people = [
{'name': 'Person 1',
'hireDate': new Date('Jun 1, 2013')},
{'name': 'Person 2',
'hireDate': new Date('Aug 1, 2012')},
{'name': 'Person 3',
'hireDate': new Date('May 1, 2011')},
{'name': 'Person 4',
'hireDate': new Date('Jun 1, 2012')},
{'name': 'Person 5',
'hireDate': new Date('Mar 1, 2014')},
{'name': 'Person 6',
'hireDate': new Date('Mar 1, 2014')},
];
});
plunker:
http://plnkr.co/edit/9zOWxJdMNg5zHz7qYf7c
You can pass the property name in as an additional parameter to the filter- like so (using an additional colon separator):
DateAgeFilter:maxLookBack:'hireDate'
Below is an example of changing your filter to make use of that, with 2 changes:
1) The additional parameter- I've called it field here.
2) In order to use the parameter to specify the property, we switch from dot notation to bracket notation- changing items[i].hireDate.getTime() into items[i][field].getTime()
app.filter('DateAgeFilter', function(){
return function(items, maxage, field) {
var minDate = new Date()
minDate.setMonth(minDate.getMonth() - maxage);
var result = [];
for (var i=0; i<items.length; i++) {
if (items[i][field].getTime() > minDate.getTime()) {
result.push(items[i]);
}
}
return result;
};
});
updated plunker

How can I horizontally expand a combobox in jqGrid upon pull-down to display all content?

How can I horizontally expand a combobox pull-down display?
My actual data is: ARAMEX1234
But the pull-down display only shows: ARAMEX123
I need to support the following browsers: IE 6, 7, 8.
I tested it using Firefox and it works out of the box. However, my application will be run on IE and never on FF.
Here is the code (jsp file content):
<%# page pageEncoding="UTF-8" contentType="text/html;charset=UTF-8"%>
<script type="text/javascript" src="<c:url value="/js/jquery/grid.locale-ja.js" />" charset="UTF-8"></script>
<link type="text/css" rel="stylesheet" href="<c:url value="/css/jquery/ui.jqgrid.css" />"/>
<script src="<c:url value="/js/jquery/jquery.jqGrid.min.js" />" type="text/javascript"></script>
<table id="rowed5"></table>
<script type="text/javascript" charset="utf-8">
var lastsel2;
$("#rowed5").jqGrid({
datatype: "local",
height: 250,
colNames:['ID Number','Name', 'Stock', 'Ship via','Notes'],
colModel:[
{name:'id',index:'id', width:90, sorttype:"int", editable: true},
{name:'name',index:'name', width:150,editable: true,editoptions:{size:"20",maxlength:"30"}},
{name:'stock',index:'stock', width:60, editable: true,edittype:"checkbox",editoptions: {value:"Yes:No"}},
{name:'ship',index:'ship', width:90, editable: true,edittype:"select",editoptions:{value:"FE:FedEx;IN:InTime;TN:TNT;AR:ARAMEX;AR1:ARAMEX123456789"}},
{name:'note',index:'note', width:200, sortable:false,editable: true,edittype:"textarea", editoptions:{rows:"2",cols:"10"}}
],
caption: "Input Types",
resizeStop: function (newwidth, index) {
var selectedRowId = $("#rowed5").getGridParam('selrow');
if(selectedRowId) {
//resize combobox proportionate to column size
var selectElement = $('[id="' + selectedRowId + '_ship"][role="select"]');
if(selectElement.length > 0){
$(selectElement).width(newwidth);
}
}
}
,
onSelectRow: function(id){
if(id && id!==lastsel2){
//$(this).saveRow(lastsel2, true);
$(this).restoreRow(lastsel2);
$(this).editRow(id,true);
lastsel2=id;
$(this).scroll();
//resize combobox proportionate to column size
var rowSelectElements = $('[id^="' + id + '_"][role="select"]');
if(rowSelectElements.length > 0) {
$(rowSelectElements).each(function(index, element){
var name = $(element).attr('name');
var columnElement = $('#rowed5_' + name);
if(columnElement.length > 0) {
var columnWidth = $(columnElement).width();
$(element).width(columnWidth);
}
});
}
}
}
});
var mydata2 = [
{id:"12345",name:"Desktop Computer",note:"note",stock:"Yes",ship:"FedEx"},
{id:"23456",name:"Laptop",note:"Long text ",stock:"Yes",ship:"InTime"},
{id:"34567",name:"LCD Monitor",note:"note3",stock:"Yes",ship:"TNT"},
{id:"45678",name:"Speakers",note:"note",stock:"No",ship:"ARAMEX123456789"},
{id:"56789",name:"Laser Printer",note:"note2",stock:"Yes",ship:"FedEx"},
{id:"67890",name:"Play Station",note:"note3",stock:"No", ship:"FedEx"},
{id:"76543",name:"Mobile Telephone",note:"note",stock:"Yes",ship:"ARAMEX"},
{id:"87654",name:"Server",note:"note2",stock:"Yes",ship:"TNT"},
{id:"98765",name:"Matrix Printer",note:"note3",stock:"No", ship:"FedEx"}
];
for(var i=0;i < mydata2.length;i++) {
$("#rowed5").jqGrid('addRowData',mydata2[i].id,mydata2[i]);
}
</script>
This is a well-known bug in IE. You can fix it by temporarily resizing the select input on mouseover or on focus as described in the following article: Select Cuts Off Options In IE (Fix)
In your specific example, the code might look like this:
$("#rowed5 select").live({
focus: function () {
$(this).
data("origWidth", $(this).css("width")).
css("width", "auto");
},
blur: function () {
var $this = $(this);
$this.css("width", $this.data("origWidth"));
}
});

Resources