I am trying to prepare a table with dynamic rowspan in antd(data will be dynmaic)
I have data like below.
Wanted to display as below. Can you please help ?
[{"col1":"temp1","col2":"1","col3":"x"},
{"col1":"temp1","col2":"1","col3":"y"},
{"col1":"temp1","col2":"2","col3":"z"},
{"col1":"temp2","col2":"3","col3":"a"}];
we can write custom render method to resolve this issue.
sample :
render: (value, row, index) => {
const obj = {
children: value,
props: {},
};
if (index >= this.state.branch_new_index) {
for (let i = 0; index + i !== metrics.length
&& value === metrics[index + i].branch &&
metrics[index].product === metrics[index + i].product; i += 1) {
obj.props.rowSpan = i + 1;
this.state.branch_count = i + 1;
}
this.state.branch_new_index = index + this.state.branch_count;
if (index + 1 >= metrics.length) {
this.state.branch_new_index = 0;
}
} else {
obj.props.rowSpan = 0;
if (index + 1 >= metrics.length) {
this.state.branch_new_index = 0;
}
}
return obj;
},
Related
I am using this <github.com/michaelbromley/angularUtils-pagination> Url code. I can able to see the data coming to UI but the pagination is not working consistantly. when there are more than 12 items the pagination is working when there are are less than 12 and more than 10 pagination is not working properly. Please refer to the URL above and suggest a solution. we are suspecting the below code. But not sure where the issue is:
function generatePagesArray(currentPage, collectionLength, rowsPerPage, paginationRange) {
var pages = [];
var totalPages = Math.ceil(collectionLength / rowsPerPage);
var halfWay = Math.ceil(paginationRange / 2);
var position;
if (currentPage <= halfWay) {
position = 'start';
} else if (totalPages - halfWay < currentPage) {
position = 'end';
} else {
position = 'middle';
}
var ellipsesNeeded = paginationRange < totalPages;
var i = 1;
while (i <= totalPages && i <= paginationRange) {
var pageNumber = calculatePageNumber(i, currentPage, paginationRange, totalPages);
var openingEllipsesNeeded = (i === 2 && (position === 'middle' || position === 'end'));
var closingEllipsesNeeded = (i === paginationRange - 1 && (position === 'middle' || position === 'start'));
if (ellipsesNeeded && (openingEllipsesNeeded || closingEllipsesNeeded)) {
pages.push('...');
} else {
pages.push(pageNumber);
}
i++;
}
return pages;
}
I'm trying to sum the values inside an array depending on which levels they are but with no success for the moment.
Datas I'm working with ( named as the variable totalByLevel ) :
What I want :
Having each total per level inside 1 array, for example : ['total of 3 + 4', 'total of 6 + 7', etc...]
What I tried :
I tried to create an empty array and push the values from 3 + 4 into the array, which is working but not as intented.
Only the last values is kept in the array and all others are erased, if you have a fix for it I would really appreciate any help! Thank you in advance.
component.ts
for (const levelKey in this.totalByLevel ) {
if (this.totalByLevel .hasOwnProperty(levelKey)) {
const key = this.labelName[levelKey];
const value = this.totalByLevel [levelKey][Object.keys(this.totalByLevel [levelKey])[0]];
const value2 = this.labelName[Object.keys(this.totalByLevel [levelKey])[0]];
const value3 = this.totalByLevel [levelKey][Object.keys(this.totalByLevel [levelKey])[1]];
const value4 = this.totalByLevel [levelKey][Object.keys(this.totalByLevel [levelKey])[2]];
this.output_object[key] = value;
this.output_object2[key] = value2;
const sum = [];
if (value4 !== undefined || null) {
sum.push((+value + +value3 + +value4).toFixed(2));
console.log(sum, 'SUM 3');
this.totalPerCat = sum;
} else if (value4 === undefined || null) {
sum.push((+value + +value3).toFixed(2));
console.log(sum, 'SUM 2');
this.totalPerCat = sum;
} else if (value3 === undefined || null) {
sum.push(value);
console.log(sum, 'SUM 1');
this.totalPerCat = sum;
}
console.log(this.totalPerCat);
/* console.log(value3);
console.log(value4);
console.log(+value + +value3 + +value4, 'SUM');*/
}
}
});
Here you go:
const data={
2:{3:"3514.80", 4:"7259.32"},
5:{6:"864941.86", 7:"1076976.54"},
8:{"":"14145.69"},
9:{10:"223835.02", 11:"60978.31", 12:"5554.92"}
}
const result = Object.values(data).map(items => Object.values(items).map(val => Number(val)).reduce((a,b) => a + b, 0))
console.log(result)
You could use the funcitons Object.values() and Array reduce in combination. Try the following
var totalByLevel = {
2: {
3: '3514.80',
4: '7259.32'
},
5: {
6: '864941.86',
7: '1076976.54'
}
};
var sum = Object.values(totalByLevel).reduce((acc, curr) => {
acc.push(String(Object.values(curr).reduce((a, c) => a + Number(c), 0)));
return acc;
}, []);
console.log(sum);
I'm trying to create a service that return me the NgTableParams so I don't need to do it every time I need a table.
I was able to do it and it worked, but only if i have only one table using it in my controller, if I try to use it in a second table look's like the service mess the parameters of the fist and second table and stop working.
I tried to change the service to a factory and tried to make a angular.copy of the service so each copy create one different table yet noting worked.
Every time i need a table it is like this:
$scope.tableParams = NgTableDataService.getGenericTableParams($scope.onboardcomputerstatus, $scope.filterObject);
$scope.searchTable = { filter: '' };
$scope.tableParams = new NgTableParams({
count: $scope.session.user.tablePagination,
filter: $scope.searchTable.filter
}, {
counts: rowsPerPageTemplate,
getData: function (params) {
var funcFilter = function (item) {
var pfilter = params.filter().filter.toUpperCase();
return item.onboardComputer.id.toString().indexOf(pfilter) >= 0
|| (!!item.onboardComputer.remainingMonitoringMsgs ? item.onboardComputer.remainingMonitoringMsgs : "").toString().indexOf(pfilter) >= 0
|| $filter('date')((!!item.onboardComputer.oldestMonitoringTimestamp ? item.onboardComputer.oldestMonitoringTimestamp : ""), Session.get().company.dateHourFormatHTML).indexOf(pfilter) >= 0
|| $filter('date')((!!item.lastCommunicatio ? item.lastCommunicatio : ""), Session.get().company.dateHourFormatHTML).indexOf(pfilter) >= 0
|| $filter('date')((!!item.lastRegister ? item.lastRegister : ""), Session.get().company.dateHourFormatHTML).indexOf(pfilter) >= 0
|| item.vehicle.code.toUpperCase().indexOf(pfilter) >= 0
|| item.vehicle.name.toUpperCase().indexOf(pfilter) >= 0;
}
filteredData = params.filter() ? $filter('filter')($scope.onboardcomputerstatus, funcFilter) : $scope.onboardcomputerstatus;
if (!!filteredData && filteredData.length >= 0) {
params.total(filteredData.length);
var rowsPerPageTemplateWithAllData = rowsPerPageTemplate.slice();
var isFound = rowsPerPageTemplateWithAllData.some(function (element) {
return element === filteredData.length;
});
var filteredDataLength = filteredData.length + (isFound ? 1 : 0);
rowsPerPageTemplateWithAllData.push(filteredDataLength);
params.settings().counts = rowsPerPageTemplateWithAllData;
if (params.count() === MY_CONSTANTS.TABLE_PAGINATION_ALL) {
params.count(filteredDataLength);
}
if (params.total() <= params.count()) {
params.page(1);
}
var x = $filter('orderBy')(filteredData, params.orderBy());
var y = x.slice((params.page() - 1) * params.count(), params.page() * params.count());
return y;
} else {
return null;
}
}
});
So I tried to do a factory like this:
angular.module('control-room').factory('NgTableDataFactory', function (
$filter, MY_CONSTANTS, NgTableParams, Session
) {
var ngTableObj = {};
ngTableObj.tableData = {};
ngTableObj.filterObject = {};
ngTableObj.session = Session.get();
ngTableObj.defaultDateFormat = (!!ngTableObj.session.company ? ngTableObj.session.company.dateHourFormatHTML : null);
ngTableObj.tablePagination = (!!ngTableObj.session.user ? ngTableObj.session.user.tablePagination : MY_CONSTANTS.QTD_REG_TAB_INDEX);
ngTableObj.NgTableParamsFactory = new NgTableParams({
count: ngTableObj.tablePagination,
filter: ""
}, {
counts: rowsPerPageTemplate,
getData: function (params) {
if (!!params.filter().filter && params.filter().filter != '') {
var pfilter = params.filter().filter.toUpperCase();
} else {
var pfilter = '';
}
let filteredData = params.filter() ? $filter('filter')(ngTableObj.tableData, ngTableObj.funcFilterFactory(ngTableObj.filterObject, pfilter)) : ngTableObj.tableData;
if (!!filteredData && filteredData.length >= 0) {
params.total(filteredData.length);
var rowsPerPageTemplateWithAllData = rowsPerPageTemplate.slice();
var isFound = rowsPerPageTemplateWithAllData.some(function (element) {
return element === filteredData.length;
});
var filteredDataLength = filteredData.length + (isFound ? 1 : 0);
rowsPerPageTemplateWithAllData.push(filteredDataLength);
params.settings().counts = rowsPerPageTemplateWithAllData;
if (params.count() === MY_CONSTANTS.TABLE_PAGINATION_ALL && filteredDataLength > 0) {
params.count(filteredDataLength);
}
var x = $filter('orderBy')(filteredData, params.orderBy());
var y = x.slice((params.page() - 1) * params.count(), params.page() * params.count());
return y;
} else {
return null;
}
}
});
ngTableObj.findPropertyValue = function (obj, propertyList){
let aux = obj;
for(property of propertyList){
aux = aux[property];
}
return aux
};
ngTableObj.funcFilterFactory = function (f_Object, p_filter) {
return function (item) {
var result = false;
if (!!f_Object.columnNames) {
f_Object.columnNames.forEach(function (row) {
if (!result){
const propertyValue = ngTableObj.findPropertyValue(item, row.split('.'));
result = (propertyValue ? propertyValue.toString() : "").toUpperCase().indexOf(p_filter) >= 0 || result;
}
});
};
if (!!f_Object.translateNames) {
f_Object.translateNames.forEach(function (row) {
if (!result){
const propertyValue = ngTableObj.findPropertyValue(item, row.split('.'));
result = $filter('translate')((propertyValue != null ? propertyValue.toString() : "").toUpperCase()).indexOf(p_filter) >= 0 || result;
}
});
}
if (!!f_Object.dateFormat) {
f_Object.dateFormat.forEach(function (row) {
if (typeof(row) == 'string') {
if (!result) {
const propertyValue = ngTableObj.findPropertyValue(item, row.split('.'));
result = propertyValue ? $filter('date')(propertyValue, ngTableObj.defaultDateFormat).toUpperCase().indexOf(p_filter) >= 0 : false || result;
}
}else {
if (!result) {
const propertyValue = ngTableObj.findPropertyValue(item, row[0].split('.'));
result = propertyValue ? $filter('date')(propertyValue, row[1]).toUpperCase().indexOf(p_filter) >= 0 : false || result;
}
}
});
}
return result;
};
};
return ngTableObj
});
and in the controller is like this:
$scope.filterObject = {
columnNames : ['onboardComputer.id', 'onboardComputer.remainingMonitoringMsgs', 'vehicle.code', 'vehicle.name' ],
dateFormat : ['onboardComputer.oldestMonitoringTimestamp', 'lastCommunicatio', 'lastRegister' ]
};
$scope.tableFactory = NgTableDataFactory;
$scope.tableFactory.tableData = $scope.onboardcomputerstatus;
$scope.tableFactory.filterObject = $scope.filterObject;
$scope.tableFactory.session = Session.get();
$scope.tableParams = $scope.tableFactory.NgTableParamsFactory
Like I said, this way it work well, but only if i use one time, if I have 2 tables it stop working
I am trying to add extra rows on a table that is generated using results.map, but the code that I have added to generate the extra rows isn't executing. Does anyone know why this wouldn't work?
< tbody >
{
results.map(result => {
let rowNodes = [];
rowNodes.push(<td className="hidden">{result.itemCtrlType}</td>);
if (this.props.gridNumber == 1) {
rowNodes.push(<td className="in-td-item">{result.metric}</td>);
} else {
rowNodes.push(<td className="in-td-item hidden">{result.metric}</td>);
}
for (const hour in result) {
if (hour.indexOf('t') == 0 && hour.length == 3) {
let now = Date.now();
let d = new Date(now);
let hours = d.getHours();
let time = hours.toString();
if (hours < 10) {
time = 't0' + hours;
}
else {
time = 't' + hours;
};
let classname = "in-td";
if (hour == time && this.props.dateAdjust == 0) {
classname += " cell-timenow";
}
if (hour == 't23') {
classname += " table-lastcolumn";
}
let date = [pad(d.getMonth() + 1), pad(d.getDate()), d.getFullYear()].join('/');
rowNodes.push(<td key={hour} className={classname} >{result[hour]}</td>)
}
}
if (this.props.gridNumber == this.props.totalGrids) {
rowNodes.push(<td className="in-td-addcolumn in-td"></td>);
}
return <tr key={result.metric} onClick={this.handleClick}>{rowNodes}</tr>
})
}
{
() => {
console.log(this.props.rowsCount > results.length);
if (this.props.rowsCount > results.length) {
let diff = this.props.rowsCount - results.length;
var rowNodes = [];
for (let m = 0; m < diff; m++) {
rowNodes.push(<td className="hidden"></td>);
if (this.props.gridNumber == 1) {
rowNodes.push(<td className="in-td-item"></td>);
} else {
rowNodes.push(<td className="in-td-item hidden"></td>);
}
for (let n = 0; n < 24; n++) {
rowNodes.push(<td className="in-td"></td>);
}
if (this.props.gridNumber == this.props.totalGrids) {
rowNodes.push(<td className="in-td-addcolumn in-td"></td>);
}
return <tr>{rowNodes}</tr>
}
}
}
}
</tbody>
I have tried various combinations of wrapping it in divs or changing where it returns but nothing seems to work.
Anyone know why this isn't firing?
First of all, that is not a good way of organising code, instead of putting the function directly inside JSX, better to define it outside of render method and then call.
Solution:
Issue with your code is, you defined a function inside JSX, but you are not calling it, Use IIFE and call that function, also return null when if condition fails, Like this:
{
(() => {
console.log(this.props.rowsCount > results.length);
if (this.props.rowsCount > results.length) {
let diff = this.props.rowsCount - results.length;
var rowNodes = [], elements = [];
for (let m = 0; m < diff; m++) {
rowNodes = [];
rowNodes.push(<td className="hidden"></td>);
if (this.props.gridNumber == 1) {
rowNodes.push(<td className="in-td-item"></td>);
} else {
rowNodes.push(<td className="in-td-item hidden"></td>);
}
for (let n = 0; n < 24; n++) {
rowNodes.push(<td className="in-td"></td>);
}
if (this.props.gridNumber == this.props.totalGrids) {
rowNodes.push(<td className="in-td-addcolumn in-td"></td>);
}
elements.push(<tr key={m}>{rowNodes}</tr>);
}
return elements;
}
return null;
})()
}
Note:
Whenever execution find return statement inside for loop, it will immediately break the loop and return that result, so instead of using return use one more variable and put the tr inside that, Return the result only after for loop completion.
Suggestion:
Assign unique key to each dynamically created elements inside loop.
Check DOC.
Check this answer for more details about keys: Understanding unique keys for array children in React.js
I've already done with my first angular app. I have an error while calling a function.
Here is a snippet of my JSON:
{
"variantA": {
"sumInsuredThirty": [
{
"dayFrom": 1,
"dayTo": 3,
"tarif": 2
}, ...
I've got it via:
$http.get("/CalculatorMed/JSON/rates.json/").then(function(data) {
$scope.rates = data.data;
});
Now, I'm trying to get the tarif:
$scope.getBaseTarif = function () {
var baseTarif = 0;
if (data.pickedOptions.variantA === true && data.pickedOptions.sumInsured === 30000) {
for (var i = 0; i < rates.variantA.sumInsuredThirty.lenght; i++) {
if (data.pickedOptions.days >= rates.variantA.sumInsuredThirty[ i ].dayFrom && data.pickedOptions.days <= rates.variantA.sumInsuredThirty[ i ].dayTo) {
baseTarif = rates.variantA.sumInsuredThirty[ i ].tarif;
return baseTarif;
}
}
}
};
And I have an error:
Error: Can't find variable: data
getBaseTarif#http://localhost:63342/CalculatorMed/controller/calculator.js:34:17
fn
Many thanks in advance!!
data cannot be access outside, it should be $scope.rates,
if ($scope.rates.pickedOptions.variantA === true && $scope.rates.pickedOptions.sumInsured === 30000) {
for (var i = 0; i < rates.variantA.sumInsuredThirty.length; i++) {
if ($scope.rates.pickedOptions.days >= rates.variantA.sumInsuredThirty[i].dayFrom && $scope.rates.pickedOptions.days <= rates.variantA.sumInsuredThirty[i].dayTo) {
baseTarif = rates.variantA.sumInsuredThirty[i].tarif;
return baseTarif;
}
}
}