I am using oracle apex version 22.1 and i'm trying to populate a page item (P617_ROW1) with some client side interactive grid data from some javascript code. So far i've been able to successfully do this through the Selection Change [Interactive Grid] event that triggers this code:
var full_record
model = this.data.model;
if(this.data != null){
if(this.data.selectedRecords[0] != null){
full_record = model.getValue(this.data.selectedRecords[0], 'LIMITTYPE')+ "/" + model.getValue(this.data.selectedRecords[0], 'AMTPERTRANS')+ "/"
+ model.getValue(this.data.selectedRecords[0],'AMTPERDAY') + "/" + model.getValue(this.data.selectedRecords[0],'NUMPERDAY')+ "/"
+ model.getValue(this.data.selectedRecords[0],'AMTPERMONTH') + "/" + model.getValue(this.data.selectedRecords[0],'NUMPERMONTH') +"/" + model.getValue(this.data.selectedRecords[0], 'SECCODE');
}
}
apex.item("P617_ROW1").setValue(full_record);
The code successfully grabs the data in each cell and formats it correctly in my page item so I can then use it for processing. The only issue is that this event forces the user to unclick and re-click the interactive grid's row selector checkbox to populate the page item. It would be a lot more efficient if this code could be triggered by another event that would not require manual user interactions (key down, page change, etc...) and would populate the page item as the user types/right before they submit. I am not proficient in JS by any means so any links that would help build my understanding of using js in oracle apex to achieve goals like this would be appreciated.
I guess I should add that I have a maximum of 4 IG rows that I need to be able to select into their respective page items. So I use the code above 4 different times with the only difference being the selected record row number (this.data.selectedRecords[n]) and the page item (P617_ROWn).
Related
Long story short, I have a long number of conditional custom fields in a WordPress site, which for reasons of length, mean I need to extract the values of currently visible select fields (i.e. not set as disabled) and combine them into a single (hidden) input field which can then be stored for internal reference purposes.
This is all happening in the backend of the WP site with a custom JS file loading.
I'm far from a JS expert, but have managed to get quite close to the desired result, but have hit a snag with the select fields needing to be first selected, and then changed in order to populate the dummy (individual) fields, which are then combined into a single input field.
Could be my entire logic is WAY off, but if anyone had any practical tips/guidance, it would be forever appreciated!
Code below with what I'm attempting to do - essentially add a dynamic class to each visible select box, then when each of these is updated, send it to an individual text field (input), and at the end, combine all of the individual text fields into one, to act as the internal reference - this is necessary as it's a user generated content site and they'll need to be able to view by the below structure.
jQuery("#select_practice select").change(function() {
jQuery('#select_practice select:not(:disabled)').each(function(i){
jQuery(this).addClass('bacon_' + i);
});
jQuery("select.bacon_0").change(function() {
jQuery("#acf-field_5a38ee98b5ff7").val(jQuery(this).val());
});
jQuery("select.bacon_1").change(function() {
jQuery("#acf-field_5a38eeaab5ff8").val(jQuery(this).val());
});
jQuery("select.bacon_2").change(function() {
jQuery("#acf-field_5a38eeb6b5ff9").val(jQuery(this).val());
});
jQuery("select.bacon_3").change(function() {
jQuery("#acf-field_5a38eec6b5ffa").val(jQuery(this).val());
});
jQuery("#select_practice select").change(function() {
jQuery("#acf-field_5a38eecfb5ffb").val(jQuery("#acf-field_5a38ee98b5ff7").val() + " | " + jQuery("#acf-field_5a38eeaab5ff8").val() + " | " + jQuery("#acf-field_5a38eeb6b5ff9").val() + " | " + jQuery("#acf-field_5a38eec6b5ffa").val());
});
});
Good evening to everybody here!
At this moment I'm working with one page in Oracle Apex (version 4.2.6.00.03). It consists of two Classic Reports — the first is a "master" one, and the second contains "details" of the former. Also there are several buttons for performing actions of inserting/updating/deleting the data. My purpose is not only to make the actions work and "details" report to refresh on choosing the row from the "master" one (I've completed these tasks), but also to manage to save the highlighting of reports' rows even after performing the actions (not only just refreshing the page).
Now I'll explain what I've already done. One can choose the row (and simultaneously highlight it) by means of the script I put in every Report's footer and it looks like this:
<script>
$(".t20data","#master_report").live("click",function(){
chooseMST($(this).find("span.MASTER").attr("id"));
});
</script>
There master_report is an ID of "master" report's region and MASTER stands for span class, in which I wrap all the cells in report to keep the value of row's ID. The function chooseMST is this:
function chooseMST(docID){
$.post('wwv_flow.show',
{'p_request' : 'APPLICATION_PROCESS=SET_MASTER',
'p_flow_id' : $v('pFLowId'),
'p_flow_step_id' : $v('pFlowStepId'),
'p_instance' : $v('pInstance'),
'x01' : docID},
function(data){
//refreshes "details" report
$('#detail_report').trigger('apexrefresh');
//deletes color from all the rows of "master" report
$(".t20data","#master_report").parent("tr").children().css("background-color","#F2F2F5");
//highlights the chosen row in "master" report
$("#" + String(docID)).parent("td").parent("tr").children().css("background-color","#A3BED8");
}
);
}
The action (say, AJAX callback) SET_MASTER is this:
begin
--clears the choice from "detail" report
APEX_UTIL.SET_SESSION_STATE(P_NAME => 'P400_DETAIL_RN'
,P_VALUE => NULL);
--makes the choice from "master" one
APEX_UTIL.SET_SESSION_STATE(P_NAME => 'P400_MASTER_RN'
,P_VALUE => APEX_APPLICATION.G_X01);
end;
To say about refreshing the page, I solved the problem of clearing the hidden items P400_DETAIL_RN and P400_MASTER_RN by having a process which goes before header with this PL/SQL code:
begin
:P400_DETAIL_RN := APEX_UTIL.GET_NUMERIC_SESSION_STATE(P_ITEM => 'P400_DETAIL_RN');
:P400_MASTER_RN := APEX_UTIL.GET_NUMERIC_SESSION_STATE(P_ITEM => 'P400_MASTER_RN');
end;
and the Javascript function recolorRows which is executed every time the page is loading:
function recolorRows(){
$(".t20data","#master_report").parent("tr").children().css("background-color","#F2F2F5");
if($("P400_MASTER_RN").val() != "") $("#" + String($("P400_MASTER_RN").val())).parent("td").parent("tr").children().css("background-color","#A3BED8");
$(".t20data","#detail_report").parent("tr").children().css("background-color","#F2F2F5");
if($("P400_DETAIL_RN").val() != "") $("#" + String($("P400_DETAIL_RN").val())).parent("td").parent("tr").children().css("background-color","#A3BED8");
}
The code concerning rows from "details" report is alike, so let me omit this part. Problems begin for me from performing the actions of manipulating the data. Here is the function which opens the dialog window for inserting or updating the row chosen in "master" report:
function MST_open(action){
//the part of code which finds out with what parameteres we should call the dialog window
$("#dialogFrame").attr("src",stringToCall);
$("#dialogWindow").dialog({
title:windowName,
modal:true,
width:500,
height:500,
resizable:true,
close:reloadMST //the action on closing the window
});
}
The code of reloadMST looks as follows:
function reloadMST(){
$("master_report").trigger('apexrefresh');
$("detail_report").trigger('apexrefresh');
}
And the Javascript function, which executes in the dialog window on the certain button click (for example, "Update"), is this:
function mstUpdate(){
$.post('wwv_flow.show',
{'p_request' : 'APPLICATION_PROCESS=MASTER_UPDATE',
'p_flow_id' : $v('pFLowId'),
'p_flow_step_id' : $v('pFlowStepId'),
'p_instance' : $v('pInstance'),
'x01' : apex.item("P402_SNAME").getValue()},
function(data){
//returns the ID of updated row in "msg" part of "res" variable
var res = eval("(" + data + ")");
if(res.status != "OK"){
//the code which catches the error, if it appears
} else {
parent.MST_close(res.msg);
}
}
);
}
where MST_close is this:
function MST_close(docID){
$("#dialogWindow").dialog("close");
//see this function above
chooseMST(docID);
}
So, this is a chain of Javascript and PL/SQL actions, which concerns the updating of the row from "master" report. The actions of inserting/updating/deleting the data work great, but I can't say the same about the saving of rows' color. The latter works good while I'm only choosing rows or refresh the page, but after performing, for example, the updating, the current row loses its highlighting. By debugging (say, adding the function console.log in Javascript code) I found out that the chain of actions, which must lead to saving the highlighting, executes nominally, but it looks like refreshing the report either goes after coloring or just prevents the latter.
Thus, my question is this: is there any way to save the highlight of the current row even after opening and closing the child dialog window?
I think that the problem is that after you update the value of a record in the modal window you refresh the data in the 2 reports in the main page and so you lose the highlight.
To fix this try to create a Dynamic Action on the event After Refresh on Region: Your Classic Reports that will execute the javascript function recolorRows(). You can also do it with javascript. The main ideea is that after you refresh the 2 reports (using reloadMST() or other method) you must trigger recolorRows().
Thank you, Cristian_I, very much. I've recently solved my problem. My mistake was that I hadn't done the hidden items binding in HTML-code - in other words, by means of Javascript only. Watching the behaviour of the hidden items, I'd discovered that when I tried to find their value with the help of jQuery function $("#hidden_item").val(), I got the previous values, but not the current ones (i.e. session state values). So that's why I had the highlighting unstable.
In addition to Dynamic Actions triggering right after refreshing the reports, I should have just add these strings to my function chooseMST before the "coloring" code itself:
$("#P400_MASTER_RN").val(docID); //binding to exact string
and
$("#P400_DETAIL_RN").val(""); //clearing the choice in the "details" report.
Due to this the problem with recoloring the rows have just gone away! Thus, now my page works excellent: the highlighting is stable, and even new rows are highlighted right after inserting them.
I have a table on one page in a Livecycle Designer form and would like the repeating row to duplicate to another table on a different page. I have this working on the first table on the first page to the table on the second using the exit event however, if the same information on the second table stays the same, because it is on the exit event, it does not copy to the new table on page 3.
I have this code in table 1 on page 1 on the exit event which works:
xfa.resolveNode("Month2.Performancegoals2.updates.details[" + this.parent.index + "]").projectName.rawValue = this.rawValue;
I thought this code would work using a button which unhides page 2
xfa.resolveNode("Month1.Performancegoals2.updates.details[" + this.parent.index + "]").projectName.rawValue = xfa.resolveNode("Month2.Performancegoals2.updates.details[" + this.parent.index + "]").projectName.rawValue
but this does not work. Actually when a value is placed in the field and the button is clicked, the entered value disappears.
Can anyone help? I'm out of time!
OK, looks like you're assigning values backwards. Values in Javascript are assigned from right to left. So, whatever is on the right of the '=' get put into the left side.
e.g.,
x=5; //assigns the value 5 to x
y=x; //assigns whatever is in x to y
Month1 = Month2; //Month2 is assigned to Month1.
If Month2 is blank, then Month1 becomes blank
I have three Tabs and in each tab, I have a Grid.
The data for each Grid is coming from a database, so I am using rowRenderer to populate the Grids. The following code is common for all three Grids:
<grid id="myGrid1" width="950px" sizedByContent="true" rowRenderer="com.example.renderer.MyRowRenderer">
The rows are constructed from Doublebox objects. The data is populated successfully.
The Problem:
I need to handle multiple-cell editing on the client side. The editing is done via mouse-clicking on a particular cell and entering a value.
As example let's say that the user edits first cell on the first row and the value should be
propagated to all other cells on the same row and in all three Grids (so also the two Grids which the user currently does not see, because they are in tabpanes).
I am using jQuery to do this value propagation and it works OK.
I am passing the jQuery as follows:
doublebox.setWidgetListener(Events.ON_CHANGING, jQuerySelectors);
doublebox.setWidgetListener(Events.ON_CHANGE, jQuerySelectors);
This makes it possible to change the value in 1 cell and the change is instantly (visually) seen in all other cells filtered by jQuery selectors.
The problem is that the value is visually distributed to all the cells, but when I try to save the Grid data back to the database, the background values are the old ones.
I am assuming that ZK-Grid component is not aware that jQuery changed all the cell values. Nevertheless if I manually click on a cell that already has the NEW value (enter/leave/change focus) when I save the grid the NEW value is correct in that particular cell. Maybe that's a hint how can I resolve this.
Code of how I extract the Grid values:
Grid tGrid = (Grid) event.getTarget().getFellow("myGrid1");
ListModel model = tGrid.getModel();
MyCustomRow tRow = (MyCustomRow)model.getElementAt(i);
The model for my Grid is a List of MyCustomRow:
myGrid1.setModel(new ListModelList(List<MyCustomRow> populatedList));
I have a couple of assumptions, but whatever I have tried, hasn't worked. I have in mind that jQuery events and ZK-Events are different and probably isolated in different contexts. (Although I have tried to fire events from jQuery and so on..)
Do you have any suggestions? As a whole is my approach correct or there's another way to do this? Thanks for your time in advance!
Your problem is exactly what you are expecting.
Zk has it's own event system and do not care about your jq,
cos it's jq and zk don't observ the DOM.
The ways to solve your problem.
Use the "ZK-Way":
Simply listen at server-side and chage things there.
I am not sure if not selected Tabs
are updateable, but I am sure you could update the Grid
components on the select event of the Tab.
Fire an zk-event your self:
All you need to know, is written in the zk doc.
Basically, you collect your data at client side, send
an Event to the server via zAu.send() extract the
data from the json object at serverside and update your Grids
I would prefer the first one, cos it's less work and there should not be
a notable difference in traffic.
I post the solution we came up with:
This is the javascript attached to each Doublebox in the Z-Grid
//getting the value of the clicked cell
var currVal = jq(this).val();
//getting the next cell (on the right of the clicked cell)
objCells = jq(this).parents('td').next().find('.z-doublebox');
// if there's a next cell (returned array has length) - set the value and
// fire ZK onChange Event
if (objCells.length) {
zk.Widget.$(jq(objCells).attr('id')).setValue(currVal);
zk.Widget.$(jq(objCells).attr('id')).fireOnChange();
} else { //otherwise we assume this is the last cell of the current tab
//So we get the current row, because we want to edit the cells in the same row in the next tabs
var currRow = jq(this).parents('tr').prevAll().length;
//finding the next cell, on the same row in the hidden tab and applying the same logic
objCellsHiddenTabs = jq(this).parents('.z-tabpanel').next().find('.z-row:eq(' + currRow + ')').find('.z-doublebox');
if (objCellsHiddenTabs.length) {
zk.Widget.$(jq(objCellsHiddenTabs).attr('id')).setValue(currVal);
zk.Widget.$(jq(objCellsHiddenTabs).attr('id')).fireOnChange();
}
}
The java code in the RowRenderer class looks something like this:
...
if (someBean != null) {
binder.bindBean("tBean", someBean);
Doublebox box = new Doublebox();
setDefaultStyle(box);
row.appendChild(box);
binder.addBinding(box, "value", "tBean.someSetter");
...
private void setDefaultStyle(Doublebox box) {
box.setFormat("#.00");
box.setConstraint("no negative,no empty");
box.setWidth("50px");
String customJS = ""; //the JS above
//this is used to visually see that you're editing multiple cells at once
String customJSNoFireOnChange = "jq(this).parents('td').nextAll().find('.z-doublebox').val(jq(this).val());";
box.setWidgetListener(Events.ON_CHANGING, customJSNoFireOnChange);
box.setWidgetListener(Events.ON_CHANGE, customJS);
}
What is interesting to notice is that ZK optimizes this fireOnChange Events and send only 1 ajax request to the server containing the updates to the necessary cells.
I have a page I created with jQuery, and in this page is a table where the table rows have classnames that identify them as a certain color (i.e. tr class="yellowclass").
The user is able to filter rows by clicking a checkbox that will show/hide tables of a certain color.
My problem is that the table is generated on the fly via getJSON requests. to add the new content to the table, I first do a children().remove() on the table's tbody, ($('#my_table_tbody').children().remove()), and then I use appendTo to add the new table information back in.
an example of this function is:
$('#my_table_tbody').children().remove();
$.getJSON("http://my_url.com/my_cgi_bin/my_cgi", {data: mydata}, function(j) {
var mylength = j.length;
for (var k = mylength - 1; k >= 0; k--)
$('<tr class="' + j[k].color + '"><td class="my_first_col_class">' + j[k].data1 + '</td><td class="my_second_col_class">' + j[k].data2 + '</td></tr>').appendTo($('#my_table_tbody'));
});
Now at the end of this function, I am trying to check to see if checkboxes are checked, and if so, to show/hide the new information. For example, to basically call
if (('#my_yellow_color_cb').attr('checked'))
$('.yellowclass').show();
else
$('.yellowclass').hide();
The problem is, the page isn't wanting to "remember" what has been checked. In other words, if the 'yellowclass' check box is unchecked, and the page reloads with new table data, the yellowclass class is still showing up, when it really should be hidden.
i suspect this has something to do with the DOM, and creating proper DOM elements that can be shown/hidden. But i don't know how to do this in my particular situation. I am a systems programmer, and am just doing this to program a tool that would provide our testers with some status info. i am no expert when it comes to JavaScript and have little understanding of the DOM, and can't seem to figure this one out.
How can I insert into the page so that I can properly show and hide this information?
If I update the page with new table data, and then check and uncheck boxes, then things work fine. But if I load table data, and just check the status of the boxes as they are, it's not wanting to work. Does jQuery take a little time to get DOM objects created before they can be accessed?
Thanks for any help.
Perhaps something like this?
$('#my_table_tbody').children().remove();
$.getJSON("http://my_url.com/my_cgi_bin/my_cgi", {data: mydata}, function(j) {
var mylength = j.length;
for (var k = mylength - 1; k >= 0; k--) {
var $row = $('<tr class="' + j[k].color + '"><td class="my_first_col_class">' + j[k].data1 + '</td><td class="my_second_col_class">' + j[k].data2 + '</td></tr>');
if ($('#my_yellow_color_cb:checked').length == 0 && $row.is('.yellow'))
$row.hide();
$row.appendTo('#my_table_tbody');
}
});
Basically, each row is created as a DOM fragment and then the conditional is run. If $('#my_yellow_color_cb:checked').length is 0, meaning the yellow color check box is not checked, then .hide() is executed for the row. Then, the row is added to the end of the tbody. You'll want to extend the if statement with more logic for your other colors.