jqGrid - Multiple grids on same page shows only one pager - javascript

I am writing a page with multiple jqGrids. My code follows a JavaScript MVC pattern which is going to provide an API for my HTML elements (including jqGrids). So, in the end of the day, I can create grids by calling my API. Something like:
var grid1 = new grid();
grid1.init();
var grid2 = new grid();
grid2.init();
I have done it with other javascript components and it worked great. However, when I create multiple jqGrid instances on the same page there is only one jqPager on the page attached to the last grid. Does anybody have an idea why?
Here is my code (Note that this is a simplified version, in reality I keep it separated in different .js files and also follow many other design patterns):
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/themes/redmond/jquery-ui.css" />
<link rel="stylesheet" type="text/css" href="http://www.ok-soft-gmbh.com/jqGrid/jquery.jqGrid-4.1.2/css/ui.jqgrid.css" />
</head><body>
<!-- IMPORT JS -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.14/jquery-ui.min.js"></script>
<script type="text/javascript" src="http://www.ok-soft-gmbh.com/jqGrid/jquery.jqGrid-4.1.2/js/i18n/grid.locale-en.js"></script>
<script type="text/javascript" src="http://www.ok-soft-gmbh.com/jqGrid/jquery.jqGrid-4.1.2/js/jquery.jqGrid.min.js"></script>
<script>
$(document).ready(function() {
function grid() {
//=== LOCA VARIABLES ===//
var myGrid = $('<table>').attr( "id", "useraccount-search-datagrid");
var myPager = $("<div>").attr("id", "useraccount-search-datagrid-pager");
var localData1 = {
"page" : 1,
"totalRecords" : 5,
"pageSize" : 3,
"rows" : [
{ Name : "Name 1"},
{ Name : "Name 3"},
{ Name : "Name 2"}
]
};
function publicInit(){
$("body").append(myGrid, myPager);
myGrid.jqGrid({
pager : myPager,
data: localData1.rows,
datatype : "local",
colModel : [
{ name : 'Name', index : 'Name', width : "500"}
],
localReader: {
repeatitems: false
},
rowNum : 3,
viewrecords : true,
height : "auto",
ignoreCase : true
});
}
//=== REVEALING PATTERN===//
return {
init: publicInit
}
};
var grid1 = new grid();
grid1.init();
$("body").append("<br><br>"); //Add some spacing to distinguish between both grids
var grid2 = new grid();
grid2.init();
});
</script>
</body>
</html>
Any help would be highly appreciated.

It seems to me that your code produce <table> and <div> elements with the same id attributes. So the second grid var grid2 = new grid(); just add <table> and <div> elements which already exist on the page. It's a bug. All id attributes of all element on one HTML page must be unique. So the lines myGrid = $('<table>').attr( "id", "useraccount-search-datagrid"); and var myPager = $("<div>").attr("id", "useraccount-search-datagrid-pager"); must be changed.
If you need just to assign some unique ids you can use $.jgrid.randId() method used in jqGrid internally. The code could be
var myGrid = $("<table>").attr("id", $.jgrid.randId());
var myPager = $("<div>").attr("id", $.jgrid.randId());
Moreover I strictly recommend you to use name conversion used in JavaScript. If you need to use new operator to create an object you should rename the function grid to Grid.

Related

Overriding datatables.js search behavior [duplicate]

This question already has an answer here:
Odd behavior of datatables.search function after modifying it
(1 answer)
Closed 4 years ago.
There are already several questions here on SO on this subject, however none is about my exact situation.
I have a datatable with 2 columns, one contains text input field and the other a select. The current behavior of datatables' search functionality is to search in the entire select HTML. The behvior I want is search only the chosen option.
I'm aware we can override/intercept the search/filter events, ie
$('#mapping-table_filter input', data_table.table().container())
.off('.DT')
.on('keyup.DT cut.DT paste.DT input.DT search.DT', function (e) {
data_table.search(...).draw();
});
// or
data_table.on('search.dt', function () {
});
But this does not help since .search does not accept a callback.
JSFiddle
https://jsfiddle.net/0oabx2mr/
If you search for any of "first", "second" or "third" both rows are still visible. I want to be able to search for "second" and "third" and only get the relevant row.
With slight architecture changes, your example may look like that:
var srcData = [
['firstOption', 'secondOption', 'thirdOption'],
['firstOption', 'secondOption', 'thirdOption'],
['firstOption', 'secondOption', 'thirdOption'],
['firstOption', 'secondOption', 'thirdOption']
];
var dataTable = $('#mytable').DataTable({
sDom: 't',
data: srcData,
columns: [{
title: 'Options',
render: (data, type, row) => '<select>'+row.reduce((options, option) => options += `<option value="${option}">${option}</option>`,'')+'</select>'
}]
});
var needle = null;
$.fn.DataTable.ext.search.push(
(settings, row, index) => $(dataTable.cell(`:eq(${index})`,':eq(0)').node()).find('select').val().match(needle) || !needle
);
$('#search').on('keyup', event => {
needle = $(event.target).val();
dataTable.draw();
});
<!doctype html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
</head>
<body>
<input id="search"></input>
<table id="mytable"></table>
</body>
</html>

How to wrap a seperate component in ExtJS Class. Err : Class is coming undefined

I created a new application in html and Java script. Where I am passing div id and creatinginput. My html and javascript code is given below
index.html
<head>
<title>MyInput </title>
<link rel="stylesheet" type="text/css" href="css/MyInput.css">
<script src="js/MyInput.js"></script>
</head>
<body style = "height: 500px;">
<div id="chart_line" style = "position: relative;"></div>
</body>
<script>
var myCombo = new MyInput({
"url": "data.json",
"divID": "chart_line",
});
</script>
Now it is going to javascript file MyInput.js
Here is my MyInput.js
MyInput = function(args) {
var divID = args.divID;
var div = document.getElementById(divID);
var myTable = '<input type="text" id="myInput" onclick = "openingList()" onkeyup="openingList()" style="width:30%;" >';
div.innerHTML = myTable;
}
This is creating one input field for me.
Now I want to make this happen on ExtJS app. So I am trying to use wrap into component. But This is getting failed. Error is MyInput is not defined.
My Code where I am trying to get this.
{
xtype : 'component',
width: 40,
height: 20,
padding: 20,
listeners :{
afterrender : function(me,eOpts) {
var tt = new MyInput.MyInput({
"url": "data.json",
"divID": "chart_line",
});
}
}
}
Also befor using this I added my JS and Css file in app.json
I am trying to get this afterrender.
But here I a getting error. Can anybody suggest me how to make it correct.

Get data from Materialize CSS chips

I need to get data from Materialize CSS chips, but I don't know, how.
$('.chips-placeholder').material_chip({
placeholder: 'Stanici přidíte stisknutím klávesy enter',
secondaryPlaceholder: '+Přidat',
});
function Show(){
var data = $('.chips-placeholder').material_chip('data');
document.write(data);
}
<!-- Added external styles and scripts -->
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.7/js/materialize.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.7/css/materialize.min.css">
<link href="http://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- HTML body -->
<div class="chips chips-placeholder"></div>
<button onclick="Show()" type="button">Show</button>
So, to access to the data's chip you just have to do this:
var data = $('#id of your chips div').material_chip('data');
alert(data[0].tag);`
'0' is the index of your data (0, 1, 2 , 3, ...).
'tag' is the chip content. You can also get the id of your data with '.id'.
To get data from Materialize CSS chips, use the below code.
$('#button').click(function(){
alert(JSON.stringify(M.Chips.getInstance($('.chips')).chipsData));
});
They appear to have changed the method available in the latest version.
The documentation suggests that you should be able to access the values as properties of the object, but I’ve spent an hour looking, not getting anywhere.
Until the following happened
$('.chips-placeholder').chips({
placeholder: 'Enter a tag',
secondaryPlaceholder: '+Tag',
onChipAdd: (event, chip) => {
console.log(event[0].M_Chips.chipsData);
},
During the onChipAdd event I was able to access the event. Within this object was an array of tags.
I know this isn't the documented way, however there is only so much time a client will accept when it comes billing and I must move on.
This worked great for me
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.chips');
var instances = M.Chips.init(elems, {
placeholder: "Ajouter des Tags",
secondaryPlaceholder: "+tag",
onChipAdd: chips2Input,
onChipDelete: chips2Input,
Limit: 10,
minLength: 1
});
function chips2Input(){
var instance = M.Chips.getInstance(document.getElementById('chip1')), inpt = document.getElementById('myInputField');
inpt.value = null;
for(var i=0; i<instance.chipsData.length; i++){
if(inpt.value == null)
inpt.value = instance.chipsData[i].tag;
else{
inpt.value += ','+instance.chipsData[i].tag; //csv
}
}
console.log('new value: ', inpt.value);
}
});
</script>

How can I use setInterval function for each custom control objects?

I created a custom control and created two objects of it in sapui5. in my customControl.js in onAfterRendering function I wrote a setInterval code which will update the value property of custom control periodically. I create my custom controls in my view :
<controls:customControl
id="customID1"
value="50"/>
<controls:customControl
id="customID2"
value="70"/>
Here is my control :
CustomControl.prototype.onAfterRendering = function()
{
setInterval(this.updateControl(this), 500);
}
But it seems when this method works, it updates all custom control objects with same value. So when I update the value property of first control as 52 and the value property of second control as 72. But I only can see 72 value for both controls.
I also tried to use sap.ui.core.IntervalTrigger method in my onAftering method like below:
var iT = new sap.ui.core.IntervalTrigger(500);
iT.addListener(this.updateControl, this);
but this doesn't work and I last tried to use closure but it doesn't work again.
(function(self){
var iT = new sap.ui.core.IntervalTrigger(500);
iT.addListener(self.updateGauge, self);
})(this);
#melomg, you should post some more details, including you custom control and the implementation of your updateControl function. I can only guess what's going wrong, anyway... Here is a working example (see code below) which runs just fine. Check the comments in the code for more information, especially because of the re-rendering loop issue that you might have (I can only guess this).
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SAPUI5 single file template | nabisoft</title>
<script src="https://openui5beta.hana.ondemand.com/resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-libs="sap.m"
data-sap-ui-bindingSyntax="complex"
data-sap-ui-compatVersion="edge"
data-sap-ui-preload="async"></script>
<!-- XMLView -->
<script id="myXmlView" type="ui5/xmlview">
<mvc:View
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:mvc="sap.ui.core.mvc"
xmlns:nabisoft="nabisoft">
<!-- use our custom control, see below -->
<nabisoft:CustomControl id="one" value="1" interval="500"/>
<nabisoft:CustomControl id="two" value="90000" interval="1000"/>
</mvc:View>
</script>
<script>
sap.ui.getCore().attachInit(function () {
"use strict";
//### Custom Control ###
jQuery.sap.declare("nabisoft.CustomControl");
sap.ui.core.Control.extend("nabisoft.CustomControl", {
metadata : {
properties : {
value : {type : "int"},
interval : {type : "int", default:500}
},
aggregations : {},
associations: {},
events : {}
},
init : function(){},
onAfterRendering: function (){
setInterval(this.updateControl.bind(this), this.getInterval());
},
updateControl : function () {
var iOldValue = this.getValue();
var iNewValue = iOldValue + 1;
// don't do this, because this will lead to a rerendering loop!!!
//this.setValue( iNewValue );
//instead do this here:
this.setProperty("value", iNewValue, true /*supress rerendering*/);
this.$().find("span").text(iNewValue);
},
renderer : {
render : function(oRm, oControl) {
oRm.write("<div");
oRm.writeControlData(oControl);
oRm.addClass("nsCustomControl");
oRm.writeClasses();
oRm.write(">");
oRm.write("<div>" + oControl.getId() +" : <span>" + oControl.getValue() + "</span></div>");
oRm.write("</div>");
}
}
});
//### THE APP: place the XMLView somewhere into DOM ###
sap.ui.xmlview({
viewContent : jQuery("#myXmlView").html()
}).placeAt("content");
});
</script>
</head>
<body class="sapUiBody">
<div id="content"></div>
</body>
</html>

fetch for defects not fetching across user, iteration, and project

I have researched and tried everything that I can think of to try and retrieve the actual values for the Iteration, Project, and User columns but I can never get the column data to populate for those like the name of the iteration, name of the project, and name of the submitted by user. I have read that it should be fine to do in the fetch the way I have it and others have said that you have to specify the types with something like this
types : ['defect','user','iteration','project'],
When I do that I dont ever load my grid. I have tried things like this as recommended by some
defect.Iteration.Name
OR
Iteration.Name
I could really use some help here. I also read one article saying the WSAPI no longer supports this kind of request and has to be handled in multiple queries/fetches. Anywho, here is the code that I am using...
function onLoad() {
var rallyDataSource = new rally.sdk.data.RallyDataSource(
'__WORKSPACE_OID__',
'__PROJECT_OID__',
'__PROJECT_SCOPING_UP__',
'__PROJECT_SCOPING_DOWN__');
var config = {
type : 'defect',
key : 'defects',
columnKeys : ["FormattedID", "Name", "Priority125", "Iteration", "Project", "SubmittedBy", "CreationDate", "ScheduleState", "State"],
fetch : 'FormattedID,Name,Priority125,Iteration,Project,SubmittedBy,CreationDate,ScheduleState,State',
query : '((State != "Closed") OR (ScheduleState != "Accepted"))',
order : 'Priority125'
};
var table = new rally.sdk.ui.Table(config, rallyDataSource);
table.display("tableDiv");
}
rally.addOnLoad(onLoad);
There are several things needed in order to get this to work as you're wanting:
You can fetch recursively up to a level of one deep. Thus if you want to grab a Defect's Name, Formatted ID, and the Project Name, your fetch would look like:
fetch: "Name,FormattedID,Project,Name"
Grab the data via rallyDataSource.findAll()
Post-process the data so that you feed your table all string data. I.e. clobber Object Reference fields like Project, with the Project Name instead.
Finally, populate and display the table.
Here's working example that illustrates what I think you're wanting to do (minus the "Priority 125" custom field that you have defined).
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- Copyright (c) 2011 Rally Software Development Corp. All rights reserved -->
<html>
<head>
<title>Defect Information</title>
<meta name="Name" content="Defect Information" />
<meta name="Version" content="1.32" />
<meta name="Vendor" content="Rally Software" />
<script type="text/javascript" src="https://rally1.rallydev.com/apps/1.32/sdk.js?debug=True"></script>
<script type="text/javascript">
var rallyDataSource = null;
var table = null;
function showTable(results) {
if (table) {
table.destroy();
}
var tableConfig = {
columnKeys : ["FormattedID", "Name", "Iteration", "Project", "SubmittedBy", "CreationDate", "ScheduleState", "State"],
columnWidths : ["85px", "350px", "90px", "100px", "100px", "120px", "100px", "100px" ]
};
table = new rally.sdk.ui.Table(tableConfig);
// Loop through the rows and clobber object attributes of the results collection with
// string values
for(var i = 0; i < results.defects.length; i++){
thisDefect = results.defects[i];
var iterationName = "";
// Grab value fields
if (thisDefect.Iteration != null) {
iterationName = results.defects[i].Iteration.Name;
} else {
iterationName = "Un-scheduled";
}
var projectName = thisDefect.Project.Name;
// Re-map SubmittedBy object to SubmittedBy string
submittedByDisplayName = thisDefect.SubmittedBy === null ? "": thisDefect.SubmittedBy._refObjectName;
// Clober objects with values
results.defects[i].Iteration = iterationName;
results.defects[i].Project = projectName;
results.defects[i].SubmittedBy = submittedByDisplayName;
}
table.addRows(results.defects);
table.display(document.getElementById('defectsDiv'));
}
function onLoad() {
rallyDataSource = new rally.sdk.data.RallyDataSource(
'__WORKSPACE_OID__',
'__PROJECT_OID__',
'__PROJECT_SCOPING_UP__',
'__PROJECT_SCOPING_DOWN__');
var config = {
type : 'defect',
key : 'defects',
fetch: 'FormattedID,Name,SubmittedBy,Iteration,Name,Project,Name,CreationDate,ScheduleState,State',
query : '((State != "Closed") OR (ScheduleState != "Accepted"))',
};
rallyDataSource.findAll(config, showTable);
rallyDataSource.setApiVersion("1.38");
}
rally.addOnLoad(onLoad);
</script>
</head>
<body>
<div id="aDiv"></div>
<div style="font-weight: bold;"><p>Defects</p></div>
<div id="defectsDiv"></div>
</body>
</html>

Categories

Resources