Angular Smart table + add summary rows - angularjs

I want to add summary row in Angular smart-table. The rows should not be sorted and it should be added in last.
I had tried but unable to achieve that, and I've searched a lot but was unable to find more information on Google.
Can anyone please let me know what should be the approach to add a summary row?

This kind of sorting can be done using custom sorting algorithm,by adding the same in sortAlgorithm under globalConfig (see smart-table documentation).
try this,
In html,
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<link data-require="bootstrap-css#3.2.0" data-semver="3.2.0" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
<script data-require="angular.js#1.2.17" data-semver="1.2.17" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.17/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
<script src="smart-table.debug.js"></script>
</head>
<body ng-controller="mainCtrl">
<h1>{{greetings}} Plunker!</h1>
<smart-table config="globalConfig" columns="columnsConfig" rows="items"></smart-table>
</body>
</html>
In js file,
angular.module('myApp',['smartTable.table'])
.controller('mainCtrl',['$scope',function(scope,$filter){
scope.greetings="world";
scope.items=[
{name:'mahesh',salary:10000,},
{name:'sachin',salary:15000},
{name:'varun',salary:12000},
{name:'vijay',salary:11000},
{name:'prem',salary:12500},
{name:'gandhi',salary:13000},
{name:'sathish',salary:14500},
{name:'ram',salary:20000},
{name:'siva',salary:22000},
{name:'dilli',salary:18000}
];
var i=0;
scope.totalSalary=0;
scope.calSalary=function(){
for(i=0;i<scope.items.length;i++){
scope.totalSalary=scope.totalSalary+scope.items[i].salary;
}
return scope.totalSalary;
}
var temp={name:'total',salary:scope.calSalary()};
scope.items.push(temp);
scope.globalConfig={
isPaginationEnabled:false,
selectionMode:'single',
sortAlgorithm:function customSortAlgorithm(arrayRef, sortPredicate, reverse) {
var i=0;
var sortTemp='';
var n=arrayRef.length-1;
for (i = 0; i < n; ++i)
{
for (j = i + 1; j < n; ++j)
{
if(sortPredicate==='salary'){
switch(reverse) {
case true:
if (arrayRef[i].salary > arrayRef[(j)].salary)
{
sortTemp=arrayRef[i];
arrayRef[i]=arrayRef[j];
arrayRef[j]=sortTemp;
}
break;
case false:
if (arrayRef[i].salary < arrayRef[(j)].salary)
{
sortTemp=arrayRef[i];
arrayRef[i]=arrayRef[j];
arrayRef[j]=sortTemp;
}
break;
default:
}}
if(sortPredicate==='name'){
switch(reverse) {
case true:
if (arrayRef[i].name > arrayRef[(j)].name)
{
sortTemp=arrayRef[i];
arrayRef[i]=arrayRef[j];
arrayRef[j]=sortTemp;
}
break;
case false:
if (arrayRef[i].name < arrayRef[(j)].name)
{
sortTemp=arrayRef[i];
arrayRef[i]=arrayRef[j];
arrayRef[j]=sortTemp;
}
break;
default:
}}
}
}
return arrayRef;
}
};
scope.columnsConfig=[
{label:'name',map:'name'},
{label:'salary',map:'salary'}
];
}]);
Please have a look at this plunker for the same.
Hope this solves your problem :)

Related

Diffing two Observables

I'm looking for a best way to Diff two Observables.
Filtered values from ObservableA should be emited as soon as ObservableB completes without waiting for ObservableA to complete.
<html>
<head>
<title></title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.3.0/Rx.js"></script>
<script>
const observable_a = Rx.Observable.interval(2000).take(10);//0,1,2,3,4,5,6,7,8,9
const observable_b = Rx.Observable.interval(1000).map(x=>x+3).take(5);//3,4,5,6,7
someDiffObservable(observable_a,observable_b).subscribe(console.log);//should output 0,1,2,8,9
</script>
</head>
<body></body>
</html>
Try this:
const a$ = Rx.Observable.interval(2000).take(10).share();
const b$ = Rx.Observable.interval(1000).map(x=>x+3).take(5);
Rx.Observable.combineLatest(
a$.buffer(
b$.startWith(null).last().concat(a$)
),
b$.toArray(),
(aItems, bItems) => aItems.filter(a => !bItems.includes(a))
)
.concatMap(filteredItems => Rx.Observable.from(filteredItems))
.subscribe(console.log);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.2/Rx.js"></script>
Currently i've came up with following function to diff two observables.
Is there a simpler/faster/better way to achieve this?
<html>
<head>
<title></title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.3.0/Rx.js"></script>
<script>
const observable_a = Rx.Observable.interval(2000).take(10);//0,1,2,3,4,5,6,7,8,9
const observable_b = Rx.Observable.interval(1000).map(x=>x+3).take(5);//3,4,5,6,7
function observableDiff(a,b,filter) {
if(!filter) {
filter = (value_to_check,blacklist_array)=>{
return blacklist_array.indexOf(value_to_check)===-1;
};
}
return Rx.Observable.create(observer=>{
let a_values = [];
let b_values = [];
let a_completed = false;
let b_completed = false;
a.forEach(a_value=>{
if(b_completed) {
if(filter(a_value,b_values)) {
observer.next(a_value);
}
} else {
a_values.push(a_value);
}
}).then(()=>{
a_completed = true;
if(b_completed) {
observer.complete();
}
});
b.forEach(b_value=>{
b_values.push(b_value);
}).then(()=>{
b_completed = true;
a_values.forEach(a_value=>{
if(filter(a_value,b_values)) {
observer.next(a_value);
}
});
a_values = [];
if(a_completed) {
observer.complete();
}
});
});
}
observableDiff(observable_a,observable_b).subscribe(console.log);//0,1,2,8,9
</script>
</head>
<body></body>
</html>

How to create autogenerate ID in angular?

Want to create autogenerate code in angular inputbox on refresh page
like rand(function) in php. Im using this script for this. But problem
is its vanished on page refresh not working properly.
<script type="text/javascript">
function randString(x){
var s = "OL-";
while(s.length<x&&x>0){
var r = Math.random();
s+= (r<0.1?Math.floor(r*100):String.fromCharCode(Math.floor(r*26) + (r>0.5?97:65)));
}
return s;
}
document.getElementById("referal_code").value = randString(10);
</script>
<input required type='text' class='span2' id='referal_code' ng-model='empInfo.referal_code'>
Try this
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function getNewID() {
try {
var myDate = new Date();
var varID = myDate.getHours() + "" + myDate.getMinutes() + "" + myDate.getSeconds() + "" + myDate.getMilliseconds();
if (varID.Length > 15) {
varID = varID.substr(0, 15);
}
return varID;
} catch (e) {
console.log(e.message);
}
}
function randString(x){
var s = getNewID();
return s;
}
window.onload = function(){
document.getElementById("referal_code").value = randString(10);
}
</script>
</head>
<body>
<input required type='text' class='span2' id='referal_code' ng-model='empInfo.referal_code'>
</body>
</html>
For any attribute in angular world you can use interpolation like this:
<input id="{{randString(10)}}"/>
If you want to have a certain value as id and not get lost after refresh you have to save it on some web storage (localstorage, sessionstorage).
e.g. :
function randString(x){
// ... your function's logic
//Save it in localStorage before returning it
localStorage.inputId = s;
return s;
}
document.getElementById("referal_code").value = localStorage.inputId || randString(10)

bind nested ng-repeat to model

In the following example, I should ask for the name of six students. They will be grouped according to bedroom type.
2 -> double
1 -> single
3 -> tiple
So, it means that I'll have a array of students (6 students). I would like to get their names. I was trying to create a variable like 'count' and put as ng-model of the input and increment during the loop, but it didn't work.
full html:
<!doctype html>
<html ng-app="sampleApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
</head>
<body ng-controller='SampleController'>
<div ng-repeat='i in numberOfAccommodations track by $index'>
Bedroom {{$index}}
<span ng-repeat='x in numberOfStudents[$index]'>
Student {{$index}}
<input type='text' ng-model='abroadStudents[???].name' /> <!-- this input to student model -->
</span>
</div>
<input type='button' value='test' ">
<script>
angular.module('sampleApp',[]).controller('SampleController',function($scope){
$scope.abroadStudents = new Array[6];
$scope.abroadAccommodation = new Array();
$scope.abroadAccommodation.push({ "bedroomType": 2}, { "bedroomType": 1 }, {"bedroomType": 3});
$scope.numberOfAccommodations = function()
{
var arr = new Array();
for (var i = 0 ; i < $scope.abroadAccommodation.length ; i++)
{
arr.push(i);
}
return arr;
}();
$scope.numberOfStudents = function()
{
var arr = new Array();
for (var x = 0 ; x < $scope.abroadAccommodation.length ; x++)
{
var temp = 0;
var intArr = new Array();
do
{
intArr.push(temp);
temp++;
}
while(temp < $scope.abroadAccommodation[x].bedroomType);
arr.push(intArr);
}
return arr;
}();
});
</script>
</body>
</html>
I rewrote your logic to create a more logical structure of objects which does not require relying upon the $index. It creates an Array of room objects, then iterates through the array of abroadAccommodation. For each abroadAccommodation, it adds a room, and based on type, adds the appropriate number of student objects. It is then very easy to use ng-repeat to iterate through each room to identify each student.
Note I also am using angular.forEach here.
<!doctype html>
<html ng-app="sampleApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
</head>
<body ng-controller='SampleController'>
<div ng-repeat="room in rooms">
{{room.roomNum}}
<div ng-repeat="student in room.students">
{{student.bed}}
<input ng-model="student.name" />
</div>
</div>
Student List:
<div ng-repeat="room in rooms">
<div ng-repeat="student in room.students">
{{student.name}}
</div>
</div>
<script>
angular.module('sampleApp', []).controller('SampleController', function($scope) {
$scope.abroadAccommodation = new Array();
$scope.abroadAccommodation.push({
"bedroomType ": 2
}, {
"bedroomType ": 1
}, {
"bedroomType ": 3
});
$scope.rooms = function() {
var arr = [];
angular.forEach($scope.abroadAccommodation, function(type, count) {
var room = {
"roomNum": "room " + (count + 1),
students: []
};
angular.forEach(type, function(numBeds) {
for (i = 0; i < numBeds; i++) {
room.students.push({
"bed": "bed " + (i + 1),
"name": "student" + Math.random()
});
}
arr.push(room);
})
});
return arr;
}();
});
</script>
</body>
</html>
http://plnkr.co/edit/YaPo54NUBPk9AnZkGcCc?p=preview

html5 canvas script looping font

<html>
<body>
<canvas id=cvs width=400px height=400px />
</body>
<script>
var text = document.getElementById('cvs').getContext('2d');
var x = 30;
for(var j=0, k='a'; j<3; j++,k++;)
{
text.fillStyle='#000';
text.font="30px Arial";
text.fillText(k,x,30);
x=x+60;
}
</script>
</html>
the k values contains font..
then i try to print the k values 3times, but it shown "a, NaN, NaN"
please help me to get the loop of font.. thanks a lot~
There is no char-Type in JavaScript. Use .charCodeAt(0) at the String-Object "a" to get the char code and use String.fromCharCode(...) to convert the char code back to a String.
Besides: HTML-Arguments have to be quoted and width and height take no units. Units are css only!
Besides (2): There is an additional ; in your for.
<html>
<body>
<canvas id="cvs" width="400" height="400" />
</body>
<script>
var text = document.getElementById('cvs').getContext('2d');
var x = 30;
for (var j=0, k="a".charCodeAt(0); j<3; j++,k++)
{
text.fillStyle='#000';
text.font="30px Arial";
text.fillText(String.fromCharCode(k),x,30);
x=x+60;
}
</script>
</html>

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