Getting the "value" field of a jqgrid's select - jqgrid

I have defined a select in a jqgrid table as follows:
{name: 'station', index: 'station', editable: true, width: 60,
edittype:"select", defaultValue:"",
editoptions:{
dataUrl: "getStationList"
},
editrules: { required: true }
},
The getStationList returns something like:
<select>
<option value="id1">Station1</option>
<option value="id2">Station2</option>
</select>
With the current definition, the first time the combo is shown, the list of Station appears nicely (Station1, Station2,...) and the JSON contains "id1" when Station1 is selected.
But when the table updates it displays "id1" in the select combo instead of keeping showing the Station's list.
Is that a bug or I`m missing some configuration option? (probably the last)
Thanks!

I think you have already a problem during filling the grid. If you want to use ids instead of names you should use formatter: "select" additionally to edittype:'select' (see the documentation). In the case you will have to place ids in the grid during filling of the grid with data. I mean that input data for jqGrid sould contains id1 and id2 instead of "Station1" and "Station2". Only in the case you will be able to use dataUrl which provide <option value="id1">Station1</option>. The next problem is: you have to set editoptions.value or formatoptions.value instead of usage dataUrl: "getStationList". So the usage of formatter: "select" is relatively complex. What one can do is to send the data like {"id1":"Station1", "id2":"Station2"} as a part of main grid data. One can place {stations: {"id1":"Station1", "id2":"Station2"}} as userdata part of JSON input (see the documentation). Inside of beforeProcessing callback one could set formatoptions.value based of userdata.stations. In the way one would de facto make request to getStationList not only during editing of data, but additionally during every filling of grid.
I personally prefer to use no formatter: "select" and use selects in the form
<select>
<option value="Station1">Station1</option>
<option value="Station2">Station2</option>
</select>
In the way the client code would "know" nothing about implementation details of the representation of data. One would fill grid with the data "Station1" and "Station2" and send the same data during editing of grid. The server on the other side will get ids by the names whenever it's needed. Typically if I create "lookup" table Stations with column like "Id" and "Name" I would set
CONSTRAINT UC_Stations_Name UNIQUE NONCLUSTERED (Name ASC)
So there are unique index in the table which can get Id by Name. In the way all Update statements with Name are exactly so quickly as with Id. I use Id in all internal SQL statements, but send only Name to external source. In the way I don't need use formatter: "select".

Related

how to correctly render referenced entities in list when I have objects instead of numberic ids?

right now in order for the list to render properly I need to have this kind of data passed in:
row = {
id: value,
name: value,
height: value,
categories: [1,2,3,4]
}
how can I adapt the code so that a list works with this kind of data?
row = {
id: value,
name: value,
height: value,
categories: [{id: "1"},{id: "2"},{id: "3"},{id: "4"}]
}
when I try to do that it seems that it applies JSON.stringify to the objects so it is trying to find category with id [Object object]
I would to avoid a per case conversion of data as I do now..
it seems that I cannot do anything in my restClient since the stringify was already applied
I have the same issue when I fetch just one data row e.g in Edit or Create.. categories ReferenceArrayInput is not populated when categories contains objects
Have you tried using format?
https://marmelab.com/admin-on-rest/Inputs.html#transforming-input-value-tofrom-record
Might help transform your input value. Then you can use format() to change values back to the format your API expects.
If this does not work then you will have to probably create a custom component out of ReferenceArrayInput.

Free jqGrid. Getting column names in conjunction with a cell

I'm trying to implement a data fullness check with an error output that describes which cells were not filled in the line.
//get row id
var gr = $("#" + subgrid_table_id).jqGrid('getGridParam', 'selrow');
// check row select
if (gr != null) {
/*
var myGrid = $("#" + subgrid_table_id),
selRowId = myGrid.jqGrid('getGridParam', 'selrow'),
//get cell value:
col1Value = myGrid.jqGrid('getCell', selRowId, 'stage');
//get all colnames
var columnNames = myGrid.jqGrid('getGridParam','colNames');
//get column name by index:
var col1Name = columnNames[4];
if (col1Value == "") {
alert("This data is empty: "+col1Name);
}
else {
That is, everything seems to work, but when you change the number of columns, everything can go to waste. How can I link the column name to ColNames with its name in ColModel to get a dynamic solution?
First of all all parameters of jqGrid are saved in one object available by myGrid.jqGrid('getGridParam'). Thus var selRowId = myGrid.jqGrid('getGridParam', 'selrow'); is the same as p.selrow, where var p = myGrid.jqGrid('getGridParam');.
The columns will be identified by the index in the colModel: p.colModel[iCol]. On the other side the name property of the column will be known more frequently as the index of the column iCol. Moreover, there are exist the possibility to reorder the columns by drag and drop of the column headers. One need include sortable: true option of the grid to enable the possibility. The column order can be changed by columnChooser or by direct calls of the methods remapColumns or remapColumnsByName. Because of all the reasons it's recommend to save the name of columns (which will be never changed) instead of the column index.
To get the column index by the column name one can loop over colModel array and test the value of the name property. To speed-up such operation free jqGrid provided the map object iColByName as the option of jqGrid. Thus, if you know the column name cmName then you can use var iCol = p.iColByName[cmName]; to get the column index. The column in colModel will be p.colModel[iCol] and the text of the column header will be p.colNames[iCol].
By the way, I'm not sure that you correctly understand the value of colNames. The name of the parameter is not good, but it will be used because of the compatibility with the old version. The elements of the array colNames are HTML fragments, which will be placed in the column headers. One can have empty strings inside of colNames or to have the same headers for different columns. On the other side the name property of the colModel is the real name of the column. It can't be empty. One can't use duplicate names in different columns and the names can't contains spaces.
I hope that having the above information you will easy able to find full information about every column.
The final remark. There are three main methods, which can be used to get data of the grid: getCell, getRowData and getLocalRow. jqGrid get input data, formats the data and places the formatted HTML fragments in the cells (in <td>). Additionally jqGrid saves the original raw data in internal data parameter (which is array of items, represented the rows). The data parameter exists only in case of using local data (datatype: "local") or in case of loading the data from remote set (datatype: "json" or datatype: "xml"), but with loadonce: true option additionally. The methods getCell and getRowData unformats the data from the cell(s) (from <td>) and the method getLocalRow get you direct reference to internal JavaScript object from internal data, where the data of the row are already set. Thus, it's recommended to prefer to use getLocalRow instead of getCell or getRowData whenever the grid has local data.

What is the way to do it with Vuejs

I have a page with 3 combos, 6 dependents inputs text ( if a special value is selected in combo, it will show, otherwise it will hide)
Then, I will have A text fields that is a computed property. Each time an input is changed, it will reevaluate this field value.
So, For instance, My fields are:
GradeIni, GradeFin, Category, AgeCategory, AgeIni, AgeFin , Gender (selects)
isTeam ( Checkbox )
CategoryFullName
So, for example, There is 5 predefines AgeCategory,and the 6th is Custom, when Selected, it show AgeIni and AgeFin
Each time a value is change, CategoryFullName is reevaluated.
My first answered question was how to get values from server.
I knew how to do it with Ajax, but in this case, it was easier to just use Server variable sent by Laravel when pages load.
So, the answer was 2 options:
#foreach ($grades as $grade)
<option ...>{{ $grade }}</option>
#endforeach
Or
<grades :grades="{{ $grades }}"></grades>
So, I would like to use the second one, but it means I have to create a component for each Select Option in my page, which seems a little heavy.
So, I'm a little bit confused about how should I make this page. Is it better by AJAX, is it better to be able to get data from laravel, and o make a component for each list, or is there a better way to do it????
You dont need to use many components. One component and one variable to keep the selected grade are fine.
You can create a component template to display all the grades.
I have created one template with dummy data to show you how you can do it.
<template id="grades-list">
Curently selected: Title {{selected.title}} Value: {{selected.value}}
<select v-model="selected">
<option v-for="grade in grades" :value="grade">{{grade.title}}</option>
</select>
</template>
The component should be registered like this:
Vue.component('grades', {
props: ['grades', 'selected'],
template: '#grades-list'
})
The tricky part is how you will select a default value and keep it synced with the parent. To do so, you can use .sync
<!-- you can use :grades="{{ grades }}" with Blade too-->
<grades :grades="grades" :selected.sync="selectedGrade"></grades>
To set default value you can update the selectedGrade variable when the document is ready, using vm.$set.
new Vue({
el: 'body',
data: {
'selectedGrade': ''
},
ready() {
this.$set('selectedGrade', this.grades[1])
}
})
I have created an example with dummy data here.

Ternary Conditional Operator not returning true/false

I have a user setting for admins that will show a delete button if they're an admin, and hide it if they're not an admin. What I'd like to say is "If the delete button is visible, the heading of this table column will say "View/Delete". If you're not an admin, the heading will say "View."" I'm also using a JS plugin called jQgrid, which is why the code is in the ColModel block. So far, it's returning true (showing "View/Delete") for everyone, even if they aren't an admin. Any suggestions? Please be nice - I'm new at this :)
, colModel: [
{ name: $(".delete:visible") ? 'View/Delete' : 'View',
The text of the header of the column of the table should have no direct relation with the value of name property of colModel. You can't dynamically change name of any column without recreating of the whole grid.
What you probably need is setLabel method which allows to change the text or attributes on any grid column. For example you can have the column {name: "view", ...} and colNames: [..., "View", ...]. To change the text "View" to "View/Delete" you need to execute
$("#gridid").jqGrid("setLabel", "view", "View/Delete");

jqgrid inline saving with clientArray throws error

I am new to jqGrid and have created a simple grid with local data with editurl set to clientArray. I am using inline navigation. I can edit a row and when I press the save button, the rows gets update. So far so good.
When I press on add row button, a new empty is row is inserted. When I type in there some data and click on the save button, I get the error message:
Uncaught TypeError: Cannot read property 'extraparam' of undefined jquery.jqGrid.min.js:398
The documentation only tells how the saveRow method should be called. But, apparently the inline navigator is calling it automatically. Which is perfect. But I guess I still need to set some parameters correctly so that it does not throw the error and saves the newly added row.
Hope some jqGrid guru has a good tip. Thanks.
function createTable(data,colNames,colModel,caption ){
...
$(table).jqGrid({ data:data,
datatype: "local",
height: 'auto',
colNames:colNames,
pager:'#'+pagerid,
colModel:colModel,
viewrecords: true,
caption:caption,
editurl:'clientArray',
});
var nav = $(table).jqGrid('navGrid','#'+pagerid,{edit:false,add:false,del:false});
$(table).jqGrid('inlineNav','#'+pagerid);
$(table).jqGrid('gridResize',{minWidth:350,maxWidth:800,minHeight:80, maxHeight:350});
$('#gbox_'+tableid).draggable();
}
You are right, It's a bug in inlineNav method. The lines
if(!o.addParams.addRowParams.extraparam) {
o.addParams.addRowParams.extraparam = {};
}
uses o.addParams.addRowParams.extraparam, but default value of parameter of addParams (see here) defined as addParams : {} and not as addParams : {addRowParams: {}}. So the expression o.addParams.addRowParams is equal undefined and o.addParams.addRowParams.extraparam is the same as undefined.extraparam which produce null reference exception.
I posted the corresponding bug report to trirand and the problem will be fixed in the next version of jqGrid.
As a workaround you can replace the line
$(table).jqGrid('inlineNav','#'+pagerid);
with the line
$(table).jqGrid('inlineNav','#'+pagerid, {addParams: {addRowParams: {}}});
Some common additional remarks to your code:
I strictly recommend that you always use gridview: true option which will improve performance of your code without any disadvantages
I recommend you to use autoencode: true option per default. Per default jqGrid interpret input data of the grid as HTML fragments which must be well formatted. So if you would try to display the data like a < b you can have problems because < is special character in HTML. If you would use autoencode: true option the input data will be interpreted as text instead of HTML fragments.
I recommend you remove index property from your model if you assign always the same value for index and name properties.
I recommend you to provide id property with unique values for every item of the input data. You should understand that jqGrid always assign id attribute for every row of grid. The value must be unique over all HTML elements on the page. If you get the data from the server and the data have native unique id from the database it's recommended to use the value as the value of id property. If you don't specify any id property jqGrid assign values 1, 2, 3, ... as the id values of rows (rowids). If you use more as one jqGrids on the page and don't provide unique id values you will have id duplicates which is HTML error.
I recommend you to use idPrefix option of jqGrid. If you have two grids on the page and you don't fill (and don't need) any id for data items then you have have id duplicates (id="1", id="2" etc in both grids). If you would define idPrefix: "g1_" for one grid and idPrefix: "g2_" option for another grid then the rowids of the first grid will be id="g1_1", id="g1_2" etc in the first grid and id="g2_1", id="g2_2" in the second grid. Even if you fill the id from the server then you provide unique id inside one table, but the ids from two tables of database can have the same id. So the usage of different idPrefix option for every grid will solve the problem of id duplicates in very simple way.
I'm having this same issue but my jqgrid markup is completely different (maybe newer version?)
I can use inline to edit and save a row, but adding a row will not save. I am not sure what the issue is.
<?php
ini_set("display_errors","1");
require_once 'jq-config.php';
// include the jqGrid Class
require_once ABSPATH."php/jqAutocomplete.php";
require_once ABSPATH."php/jqCalendar.php";
require_once ABSPATH."php/jqGrid.php";
// include the driver class
require_once ABSPATH."php/jqGridPdo.php";
// Connection to the server
$conn = new PDO(DB_DSN,DB_USER,DB_PASSWORD);
// Tell the db that we use utf-8
$conn->query("SET NAMES utf8");
// Create the jqGrid instance
$grid = new jqGridRender($conn);
// Write the SQL Query
$grid->SelectCommand = 'SELECT Serial, Type, Customer, Date, Notes FROM rmas';
$resize = <<<RESIZE
jQuery(window).resize(function(){
gridId = "grid";
gridParentWidth = $('#gbox_' + gridId).parent().width();
$('#' + gridId).jqGrid('setGridWidth',gridParentWidth);
})
RESIZE;
$grid->setJSCode( $resize);
// set the ouput format to json
$grid->dataType = 'json';
$grid->table ="rmas";
$grid->setPrimaryKeyId("Serial");
// Let the grid create the model
$grid->setColModel();
// Set the url from where we obtain the data
$grid->setUrl('rmaform.php');
$grid->cacheCount = true;
//$grid->toolbarfilter = true;
$grid->setGridOptions(array(
"caption"=>"RMAs",
"rowNum"=>50,
"sortname"=>"Serial",
"hoverrows"=>true,
"rowList"=>array(50,100,200),
"height"=>600,
"autowidth"=>true,
"shrinkToFit"=>false
));
$grid->callGridMethod('#grid', 'bindKeys');
// Change some property of the field(s)
$grid->setColProperty("Serial", array("align"=>"center","width"=>40));
$grid->setColProperty("Type", array("align"=>"center","width"=>40));
$grid->setColProperty("Customer", array("align"=>"center","width"=>65));
$grid->setColProperty("Date", array("align"=>"center","width"=>40));
$grid->setColProperty("Notes", array("align"=>"left","width"=>500));
// navigator first should be enabled
$grid->navigator = true;
$grid->setNavOptions('navigator', array("add"=>false,"edit"=>false,"excel"=>true));
// and just enable the inline
$grid->inlineNav = true;
$buttonoptions = array("#pager", array(
"caption"=>"Enable Cells",
"onClickButton"=>"js:function(){ jQuery('#grid').jqGrid('setGridParam',{cellEdit: true});}", "title"=> "Enable Excel like editing"
)
);
$grid->callGridMethod("#grid", "navButtonAdd", $buttonoptions);
$buttonoptions = array("#pager", array(
"caption"=>"Disable Cells",
"onClickButton"=>"js:function(){ jQuery('#grid').jqGrid('setGridParam',{cellEdit: false});}" , "title"=> "Disable Excel like editing"
)
);
$grid->callGridMethod("#grid", "navButtonAdd", $buttonoptions);
$grid->renderGrid('#grid','#pager',true, null, null, true,true);
$conn = null;
?>

Resources