web2py sqlform grid links on left join problems - hyperlink

I have a custom controller in SQLFORM.grid and I am using links. The problem is (so it appears) that since I am using left join there when my custom function works, edit and view do not work.
So my links is the following
links = [lambda row: A('',_class='glyphicon glyphicon glyphicon-remove-sign',
callback=URL('settings','deactivate',vars=dict(table='workers_skills',field = 'ws_status'
,value = row.workers_skills.id )))]
my grid constructor
grid_workersskills= SQLFORM.grid(query=query,left=[db.workers.on(db.workers_skills.ws_worker==db.workers.id),
db.skills.on(db.workers_skills.ws_skill==db.skills.id)],
fields=fields, searchable=False, orderby=[db.workers.w_nick_name],create=True,
deletable=False, editable=True, paginate=50, buttons_placement = 'right',
showbuttontext = False,
links = links,
#oncreate=myfunction,
ui = dict(widget='',
header='',
content='',
default='',
cornerall='',
cornertop='',
cornerbottom='',
button='button btn btn-default',
buttontext='buttontext button',
buttonadd='icon plus icon-plus glyphicon glyphicon-plus',
buttonback='icon leftarrow icon-arrow-left glyphicon glyphicon-arrow-left',
buttonexport='icon downarrow icon-download glyphicon glyphicon-download',
buttondelete='icon trash icon-trash glyphicon glyphicon-trash',
buttonedit='icon pen icon-pencil glyphicon glyphicon-pencil',
buttontable='icon rightarrow icon-arrow-right glyphicon glyphicon-arrow-right',
buttonview='icon magnifier icon-zoom-in glyphicon glyphicon-eye-open',
),
exportclasses = dict(csv_with_hidden_cols=False, html = False, tsv = False, tsv_with_hidden_cols=False, json = False))
the problem is caused by row.workers_skills.id
If i keep it this way my function deactivate works ok, but when I click on edit or view of the record I get an error
Row attribute has no object workers_skills
If I put it to row.id the view and edit work, but my deactivate function not because ID or the record is not created.
I have been struggling with this for the last week. Please help
Thank you

When the grid involves a join, you must refer to fields within a row via the row.table.field format. However, when you view/edit a record from such a grid, only the record from a single table is shown (i.e., there is no longer a join involved), so you must now refer to fields within a row via the row.field format. Because your "link" appears in the grid as well as in the view/edit page, whichever format you use to refer to the id field, it will result in an error in one of those two contexts.
So, all you need to do is ensure your code works in both contexts. Here's a simple trick:
Instead of:
row.workers_skills.id
do:
row.get('workers_skills', row).id
The .get() method attempts to retrieves the 'workers_skills' key, but if it doesn't exist, it instead returns a default value, which in this case is just the original row. It then retrieves the "id" field of that returned object (either the original row or the row.workers_skills sub-row).

Related

antd prepopulate tags and multi select

I'm working on antd select and having issues with prepopulating it correctly, I can prepopulate the select box via its initialValue field decorator, however it populates strings, there does not appear to be a way to have a value (something I can work around but not ideal), and more importantly if the option is unselected/removed, it is no longer available in the select, unlike standard options. I can include in both select list options and initial value (as demonstrated in code below) but then it allows duplicate auto entry and it appears twice in the drop down list. Any ideas what I'm doing wrong?
Preperation of Preselected and Full Option List
let defaultSelect = [];
let selectList = [];
for (var a = 0; a < this.props.myData.length; a++) {
//push all options to select list
selectList.push(<Select.Option key={this.props.myData[i].id} >{this.props.myData[i].name}</Select.Option>)
//this is my code to pre-populate options, by performing a find/match
let matchedTech = _.find(this.props.myDataPrepopulate, { id: this.props.myData[i].id });
if (matchedTech) {
//notice I can push just the string name, not the name and the id value.
defaultSelect.push(this.props.myData[i].name);
}
}
Select Code
{getFieldDecorator(row.name, {
initialValue: defaultSelect
})(
<Select
tags
notFoundContent='none found'
filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
{selectList}
</Select>
)}
I think I understand your question, even if you posted code that doesn't run.
<Select.Option> works just like the plain html <select><option/></select>. In order to give the option a value it needs a value attribute, which is used to identify the option.
See http://codepen.io/JesperWe/pen/YVqBor for a working example.
The crucial part transformed to your example would become:
this.props.myData.forEach( data => {
selectList.push(<Select.Option value={data.id} key={data.id}>{data.name}</Select.Option>);
} );
defaultSelect = this.props.myDataPrepopulate.map( data => data.id );
(I took the liberty to use a bit more modern code patterns than your original)

MVC "Editfor" Element for a "List<string>" with the option to add new elements

I need way to display a "List" property with the option to add new elements to the list.
So Basically
Value 1
Value 2
Button: Add new
I created an editfor template for it, where I display all the values with a foreach loop. However, each item get's an index, so when I add a new input field with javascript, the index is wrong.
Any suggestions how to achieve this.
PS: the adding of new elemens mustbe done on the client, since it is a simple form
var abccounter = 1;
$("#abcbutton").click(function () {
$('#itemlist').append('<p><input class="text-box single-line" id="listofstringname_' + abccounter + '_" name="listofstringname[' + abccounter + ']" type="text" value=""></p>');
abccounter++;
});
<p>#Html.EditorFor(model => model.listofstringname)</p>
that is what I did and it worked. the only problem I'm having (and it may be solved eventually) is I want to wrap each element with a tag but I'm not sure how. this JS just adds a new "text box element" assuming 1 as the start as my model loads 1 example by default.

Why is MVC Html.RadioButton working like a checkbox instead of like a radio button?

In these code I have a strange situation:
#foreach (var subs in getSubscriptionTypes())
{
<p>#Html.RadioButton(subs.LengthMonths.ToString(), subs.Price) #subs.LengthMonths</p>
}
I get properly all of subs, but radiobuttons behave very strange - I can check all of radiobuttons, but I want to check only one (one is true, then rest is false). How to repair it?
Regards.
The first parameter of each radio button needs to be the same for them to be mutually exclusive (see this demo).
So try:
<p>#Html.RadioButton("subtype", subs.Price) #subs.LengthMonths</p>
For a better user interface, you could also add a label element using #Html.Label(...) so that the user can click on the text to select the radio:
<p>
#Html.RadioButton("subtype", subs.Price, new { id = "subtype-" + subs.Price })
#Html.Label("subtype-" + subs.Price, #subs.LengthMonths)
</p>

Can not select row in subgrid : Jqgrid

I am using jqgrid, and added one subgrid inside it, which looks like as below,
As you can see,
Rows with columns having 11 and 13 are main grid rows
And every row has subgrid having interest,
The Add Record element shows Add Pop up for Subgrid
Here is the code for subgrid looks like,
subGridRowExpanded: function(subgrid_id, row_id) {
var subgrid_table_id, pager_id;
subgrid_table_id = subgrid_id+"_t";
pager_id = "p_"+subgrid_table_id;
$("#"+subgrid_id).html("<table id='"+subgrid_table_id+"' class='scroll'></table><div id='"+pager_id+"' class='scroll'></div>");
jQuery("#"+subgrid_table_id).jqGrid({
url:"shops?q=2&ShopID="+row_id,
datatype: "xml",
colNames: ['Interest'],
colModel: [
//{name:"Id",index:"ShopID",width:80,editable:false,editoptions:{readonly:false,size:40}}, //Shop ID not required
{name:"id",index:"id",editable:true,edittype:"select",editoptions:{dataUrl:'shops?q=3&ShopID='+row_id},editrules:{required:true}}
],
rowNum:10,
pager: pager_id,
width: '100%',
height: '100%',
scrollOffset: 0,
sortname: 'num',
sortorder: "asc",
height: '100%',
editurl:'shops?q=5&ShopID='+row_id
});
jQuery("#"+subgrid_table_id).jqGrid('navGrid',"#"+pager_id,{edit:false,add:true,del:true})
},
subGridRowColapsed: function(subgrid_id, row_id) {
// this function is called before removing the data
//var subgrid_table_id;
//subgrid_table_id = subgrid_id+"_t";
//jQuery("#"+subgrid_table_id).remove();
}
Problem is , when there are more than one element in subgrid, i can select that (I use latest version of Chrome) but when there is only single element in subgrid surprisingly I can select it ( if you notice the color difference please see subgrid element 'Gifts' -selected below row 13 ) and once select that 'Gifts' can be deleted.
UPDATE:
In firefox and IE , only first row gets selected from subgrid
Is there something wrong in the code ? why can't i select single element when there are more than one elements in subgrid ?
Appreciate your time, thanks
I suppose that you have problem with id duplicates. HTML don't allow to use id attributes on the same HTML pages with the same values. The values of all id attributes must be unique. I recommend you to verify that you have the problem by usage of Developer Tools of Chrome/IE or using Firebug. You need just examine the id attributes which you have now on <tr> elements of grid and subgrids.
On the other side all rows (all <tr> elements) of jqGrid become an id attribute assigned. Typically you have to fill id in the server side in the response of url. The problem is that one use typically the values from id from the database, but you have typically unique id only over one table of the database and not over all tables on the database. So you can easy have the scenario where multiple jqGrids (or grid with subrird) get rows with id duplicates.
The most easy way to fix the problem is to use idPrefix option which was introduced in jqGrid after my suggestion. The main advantage is that you can continue to use the original id values which you have in the database and use id attributes in jqGrid which will be unique because of building id attributes from the id values returned from the server, but with the usage of prefixes. In the answer. So I recommend you to use different idPrefixes for all subgrids. For example you can use idPrefix: 's' + row_id + '_' in subgrid (see the answer and this one).

How to delete a jqgrid row without reloading the entire grid?

I have a webpage with multiple jqgrids each with inline editing enabled, "action" column (edit icons) enabled and pager disabled. I need to handle the delete event for each row so that I can process the delete without reloading server-side data. I've looked at the approach mentioned in jqGrid Delete a Row and it's very helpful except I have two questions that are stumping me -
Are there more details around the rp_ge parameter in the delOptions.onClickSubmit event?
My column has the delOptions set as this -
delOptions: {onclickSubmit: function(rp_ge, rowid) {return onRowDelete(rp_ge,rowid);}},processing:true }},
Is there a way to get the grid id from within that event? I'd like to have a generic function that I can use to handle delete events from all the grids on the page. The rp_ge parameter has a gbox which sometimes contains the grid id appended? But I have no idea what it is since i'm not able to figure out when it's populated, when it's not.
function onRowDelete(rp_ge, rowid) {
//hardcoded grid id.. don't like it.
var gridid = '#Grid_X';
//what is this gbox?? can i get grid id predictable from it?
//var gridid = rp_ge.gbox.replace("#gbox_", "");
var grid = $('#Grid_X');
rp_ge.processing = true;
var result = grid.delRowData(rowid);
if (result) {
$("#delmod" + grid[0].id).hide();
}
return true;
}
In the jqGrid Delete a Row approach, the code $("#delmod"+grid[0].id).hide(); is hiding the popup delete confirmation dialog manually. What I noticed is that when the dialog pops-up, jqgrid de-emphasizes the background page (makes it light greyish). But after the popup is manually closed (hidden actually?), the background remains de-emphasized. So it looks like the page doesn't have focus (or even disabled). Any way this can be fixed? This can also be seen on the demo that Oleg wrote.
Any help would be appreciated.
(PS - I would've commented on the same post but I don't have enough points to comment on someone else's answer yet.)
In answer to your second point.
Several examples by Oleg such as this one have the following modification.
$("#delmod" + grid[0].id).hide();
is replaced with
$.jgrid.hideModal(
"#delmod"+grid_id,
{gb:"#gbox_"+grid_id,jqm:rp_ge.jqModal,onClose:rp_ge.onClose}
);
This will return focus after the delete operation.

Resources