Oracle APEX style APEX_ITEM Dynamic form elements - oracle

I followed the instructions from this post on how to create dynamic items in APEX. The documentation is clear on how to create the item but I cannot figure out how to make the item look like native APEX items.
I have attempted copying different CSS classes that I can see attached to the native items, but for the life of me I cannot get my dynamically created form elements to look and act the same.
Any help would be greatly appreciated.

Hi – just to add to Dan’s and Salim’s comments and recommendations. I agree that for this particular use case, APEX_ITEM work well. However, as Dan pointed out, the APEX_ITEM API is considered legacy code. While we may never actually remove this API from APEX, as this would break too many apps, we do not plan on developing this API further. There are many reasons, but really comes down to the APEX_ITEM API using its own code to render page items, and all new components, including standard form items and Interactive Grid form items, share the same, more modern implementation, which is fully integrated with the Universal Theme and accessible. There are also significant differences in the way form items are submitted to the server and the way this data is processed. We’re working towards providing better alternatives to the APEX_ITEM in the future.
- Marc

If you are using Chrome Browser, then the easiest way to get all the styles is to use the browser Copy styles.
Right click on an item created natively and select Inspect.
Right click on the selected HTML element under Elements tab and go to Copy => Copy styles
This will get you the styles associated with the native item. Now assign those styles to your dynamically generated item.
You need to do this for every item type.
Best Regards,
Salim

This should help:
with
TP_ORDEM_SERV_REC as (
select C.ID_FUNCAO,
C.QT_EXEC
from TB_ORDEM_SERV_REC C
where C.ID_ORDEM_SERV = :P922_ID_ORDEM_SERV
and C.NUM_TAR = :P922_NUM_TAR)
select A.DESC_SUPLEMENT FUNCAO,
'<div class="t-Form-fieldContainer t-Form-fieldContainer--floatingLabel lto'||A.ID_SUPLEMENT||' apex-item-wrapper apex-item-wrapper--text-field" id="it_'||A.ID_SUPLEMENT||'_CONTAINER">'||
'<div class="t-Form-labelContainer">'||
'<label for="it_'||A.ID_SUPLEMENT||'" id="it_'||A.ID_SUPLEMENT||'_LABEL" class="t-Form-label">Quant. Exec.</label>'||
'</div>'||
'<div class="t-Form-inputContainer">'||
'<div class="t-Form-itemWrapper">'||
'<input type="hidden" name="f01" value="'||A.ID_SUPLEMENT||'" />'||
'<input type="text" name="f02" id="it_'||A.ID_SUPLEMENT||'" class="text_field apex-item-text" value="'||A.QT_EXEC||'" size="1" maxlength="2">'||
'</div>'||
'<span id="it_'||A.ID_SUPLEMENT||'_error_placeholder" class="a-Form-error" data-template-id="'||A.ID_SUPLEMENT||'_ET"></span>'||
'</div>'||
'</div>' QT_EXEC
from TB_SUPLEMENT A,
TB_USUARIO B,
TP_ORDEM_SERV_REC C
where A.FLAG_CTRL = 15
and B.ID_OFICINA = :P922_ID_OFICINA
and A.ID_SUPLEMENT = B.ID_FUNCAO
and B.ID_FUNCAO = C.ID_FUNCAO (+)
group by A.DESC_SUPLEMENT,A.ID_SUPLEMENT,C.QT_EXEC
Then, just use apex_application.g_f to manipulate the result in the process as normal.

Related

Loop through drop down with dynamic html table

I'm hard stuck with this one so any advice welcome!
Ive been trying to create a flow that goes to this website https://dlv.tnl-uk-uni-guide.gcpp.io/ and scrapes the data from each table in the Subject Areas drop down list. My knowledge of HTML is sketchy at best but from what I understand it's a dynamic html table that just refreshes with new data rather than going to a new url. I can extract the subject list as a variable and in my head i think i just need to add this to a UI selector action but despite numerous attempts i've got absolutely nowhere. Anyone got any ideas as to how i could fix this or work around?
Because it is not a conventional drop-down using the "Set drop-down list value on web page" doesn't work all that well.
You can use a bit of javascript and variables for this.
Hit F12 to show developer tools, you will see there is a list of hidden items with the class class="gug-select-items gug-select-hide" you will use this in the javascript.
Then add a 'Press button on web page' function and add the 'drop-down' element, which is a <div>
Then edit the element selector and change it to text editor.
then change the selector to make use of the nth-child(0) selector but use a variable for the index.
so it looks something like #gug-overall-ranking-select > div.gug-select-items > div:nth-child(%ddIdx%)
Use the "Run JavaScript function on web page" function to get the number of options available to the drop-down. (child elements)
The returned result is text, so convert it to a number that can be used in the loop.
function ExecuteScript() { /*your code here, return something (optionally); */
var firstDDlist = document.querySelector("#gug-overall-ranking-select > div.gug-select-items.gug-select-hide");
return firstDDlist.children.length;
}
In the loop each element will be pressed and cause the table to reload.
The table data extraction can then also be done in the loop, but that this code only shows the looping through the options.
The full flow 'code' (copy this and paste it in power automate).
WebAutomation.LaunchEdge.LaunchEdge Url: $'''https://dlv.tnl-uk-uni-guide.gcpp.io/?taxonomyId=36&/#gug-university-table''' WindowState: WebAutomation.BrowserWindowState.Normal ClearCache: False ClearCookies: False WaitForPageToLoadTimeout: 60 Timeout: 60 BrowserInstance=> Browser
WebAutomation.ExecuteJavascript BrowserInstance: Browser Javascript: $'''function ExecuteScript() { /*your code here, return something (optionally); */
var firstDDlist = document.querySelector(\"#gug-overall-ranking-select > div.gug-select-items.gug-select-hide\");
return firstDDlist.children.length;
}''' Result=> numberOfItems
Text.ToNumber Text: numberOfItems Number=> itemCount
LOOP ddIdx FROM 1 TO itemCount STEP 1
WebAutomation.PressButton.PressButton BrowserInstance: Browser Control: appmask['Web Page \'h ... sity-table\'']['Div \'gug-select-selected\''] WaitForPageToLoadTimeout: 60
END
It should end up looking like this:
Flow running:
With using Power Automate Desktop (PAD), the goal is to be a low-code solution. Of course knowing HTML is a bonus and will help you on tricky webpages or problems, but not knowing much is alright usually. I'm not really comfortable going to that web page you shared but you could try the below option.
PAD has a built in function in the action pane:
'Browser automation' > 'Web data extraction' > 'Extract data from web page'
Try using that and when asked to add UI Element select the table/dropdown list to see what information you get back. If that doesn't work you might need to try out JavaScript or another method.

Link directly to a notebook page in a view

I have an view that extends the current project view, where we add multiple tabs (notebook pages) to show information from other parts of a project.
One of these pages is an overview page that summarizes what is under the other tabs, and I'd like to link the headlines for each section directly to each displayed page. I've currently solved this by using the index of each tab and calling bootstrap's .tab('show') method on the link within the tab:
$(".overview-link").click(function (e) {
e.preventDefault();
var sel = '.nav-tabs a:eq(' + $(this).data('tab-index') + ')';
$(sel).tab('show');
});
This works since I've attached a data-tab-index="<int>" to each header link in my widget code, but it's brittle - if someone adds a tab later, the current indices will be broken. Earlier I relied on the anchor on each tab, but that broke as well (and would probably break if a new notebook page were inserted as well).
Triggering a web client redirect / form link directly works, but I want to show a specific page in the view:
this.do_action({
type: 'ir.actions.act_window',
res_model: 'my.model.name',
res_id: 'my.object.id',
view_mode: 'form',
view_type: 'form',
views: [[false, 'form']],
target: 'current'
});
Is there any way to link / redirect the web client directly to a specific notebook page tab through the do_action method or similar on FormWidget?
If I understood well you want to select the tab from the JavaScript (jQuery) FormWidget taking into account that the id could change if anybody install another module that adds another tab
Solution 0
You can add a class to the page in the xml form view. You can use the id of the element selected by this class name in order to call the right anchor and select the right tab item. This should happen when the page is completely loaded:
<page class="nb_page_to_select">
$('a[href=#' + $('.nb_page_to_select').attr('id') + ']').click()
NOTE: As you have said the following paragrah I assume that you know where to run this instruction. The solution I suggest is independent of the index.
This works since I've attached a data-tab-index="<int>" to each
header link in my widget code, but it's brittle - if someone adds a
tab later, the current indices will be broken. Earlier I relied on the
anchor on each tab, but that broke as well (and would probably break
if a new notebook page were inserted as well).
Solution 1
When the page is loaded you can get the tab list DOM object like this:
var tablist = $('ul[role="tablist"]')
And then you can click on the specifict tab, selecing by the text inside the anchor. So you don't depend on the tab index:
tablist.find('a:contains("Other Information")').click()
I think if you have two tabs with the same text does not make any sense, so this should be sufficient.
Solution 2
Even if you want to be more specific you can add a class to the notebook to make sure you are in the correct notebook
<notebook class="nt_to_change">
Now you can use one of this expressions in order to select the tab list
var tablist = $('div.nt_to_change ul.nav-tabs[role="tablist"]')
// or
var tablist = $('div.nt_to_change ul[role="tablist"]')
Solution 3
If the contains selector doesn't convince you because it should be equal you can do this as well to compare and filter
tablist.find('a').filter(function() {
return $.trim($(this).text()) === "Other Information";
}).click();
Where "Other Information" is the string of the notebook page
I didn't tried the solution I'm giving to you, but if it doesn't work at least may be it makes you come up with some idea.
There's a parameter for XML elements named autofocus (for buttons and fields is default_focus and takes 1 or 0 as value). If you add autofocus="autofocus" to a page in XML, this page will be the displayed one when you open the view.
So, you can try to add this through JavaScript, when the user clicks on the respective link -which honestly, I don't know how to achieve that by now-. But you can add a distinctive context parameter to each link in XML, for example context="{'page_to_display': 'page x'}". When you click on the link, I hope these context keys will arrive to your JS method.
If not, you can also modify the fields_view_get method (here I wrote how to do that: Odoo - Hide button for specific user) to check if you get the context you've added to your links and add the autofocus parameter to the respective page.
As you said:
This works since I've attached a data-tab-index="" to each header
link in my widget code, but it's brittle - if someone adds a tab
later, the current indices will be broken.
I assume that your app allow multi-user interaction in realtime, so you have to integrate somewhere in your code, an update part function.
This function will trig if something has changed and cleanout the data to rebuilt the index in order to avoid that the current indices will be broken.

jqGrid: Create a custom edit form

I am wanting to customise the edit form in jqGrid so that instead of using the table structured layout provided I would like to use my own custom css structured layout for the form elements. How should I go about modifying the edit form to allow me to use my own custom look?
You can definitely achieve this by jquery ui dialog. However I can not put full code for you but helps you in the steps you have to do.
1 design your custom form whatever CSS and style you want to apply.
Suppose this is youe custome form
<div id="dialog-div">
<input type="text">
</div>
2 on jquery dialog open the dialog on your jqgrid editbutton click
$("#edit").click(function(){
var rowdata = $("#coolGrid").jqGrid('getGridParam','selrow');
if(rowdata){
$("#dialog-div").dialog('open');
var data = $("#coolGrid").jqGrid('getRowData',rowdata);
alert(data);
}
});
by default it will close as-
$("#dialog-div").dialog({
autoOpen: false,
});
Now as you get data in variable you can put in your edit form and of jquery dialog button save it according to your logic.
Hope this helps you.
I would recommend you first of all to read (or at least look thorough) the code of form editing module which implement the part which you want to replace. You will see that it consist from more as 2000 lines of code. If you write "I would like to ..." you should understand the amount of work for implementing what you ask. If you are able to understand the code and if you are able to write your modification of the code even using libraries like jQuery UI then you can decide whether it's worth to invest your time to do the work. The main advantage of using existing solutions is saving of the time. What you get in the way is not perfect, but using existing products you could create your own solutions quickly and with acceptable quality. The way to study existing products which you can use for free seems me more effective as large investments in reinventing the wheel.
http://guriddo.net/?kbe_knowledgebase=using-templates-in-form-editing
Using templates in form editing
As of version 4.8 we support templates in the form editing. This allow to customize the edit form in a way the developer want. To use a template it is needed to set the parameter template in the edit add/or add options of navigator. This can be done in navigator or in the editing method editGridRow :
$("#grid").jqGrid("navGrid",
{add:true, edit:true,...},
{template: "template string for edit",...}
{template: "template string for add",...},
...
);
and in editGridRow method:
$("#grid").jqGrid("editGridRow",
rowid,
{template: "template string",...}
);
To place the CustomerID field in the template the following code string should be inserted in the template string
{CustomerID}
With other words this is the name from colModel put in { }
The usual problem with table layouts is when you have columns with different widths, especially with those very wide.
I solved my problem adding the attr colspan to wide columns in the beforeShowForm event.
for example
"beforeShowForm":function() {
$('#tr_fieldnameasinColModel > td.DataTD').attr('colspan',5);
}
It's not fancy but it worked for me. Perhaps there is a more elegant way to do the same.
I could arrange the fields in several columns without having to make the form extrawide.
When user click on edit button the page navigate to another page, based on Id get the details of a row and you can display the values..
Previous answer of Creating a link in JQGrid solves your problem.

Updating JQuery dataTable table outside itself

I managed to get jquery datatables plugin to work with asp.net mvc 3 so it posts back json, and with a search function.
Problem now I that I need to move the search box and add a "language" filter outside it's "normal" position next to a custom made menu.
Is there a way that I can integrate:
Language: <select name="languageid">
<option value="SV">Swedish</option>
<option value="EN">English</option>
</select>
Keywords: <input type="text" name="keywords">
To refresh datatables when languageid or keywords change? and still have sorting, paging working?
My brain is only firing at half power today, but the short answer is that this can be done; it's just my suggestions that are kind of vague...sorry!
There are a whole set of language options in oLanguage; it was a bit "Too Long, Didn't Read" for me to sort through, but perhaps something there will help you identify where to set up a language switcher
You can remove the search box from the main table and set up your own, using the fnFilter method to trigger the search
Depending on how your other options are configured (server-side, for example), there are methods to trigger a refresh of the table. You would bind a listener for the languageid or keyword change action (.on('change', '#languageid', function(e) { /* ... */ })) which would fire the appropriate refresh action (in my instance which uses server-side, I use fnDraw())
I'm sorry about the directionless advice, but I wanted you to know at least that this is possible. Posting the question on the datatables.net forums directly might get you the best possible answer.

Dropdown in templated column for ultrawebgrid does not function properly

I have a templated column. I am using a Dropdown as header template and based on the value of the dropdown user sets, I update sigle DB record. Header drop down has nothing to do with the contents of the cells of that column. Everything works fine when the page is loaded and dropdown functions as expected.
As soon as I click anywhere on the gid and then click on the drop down, it behaves in a weird fashion i.e. it expands and then collapses. If I double click on the drop down it works as expected.
I am not able to understand what happens when I click inside the grid so that my drop down only responds to double click and not single click.
Here is the code snippet:
<igtbl:TemplatedColumn BaseColumnName="Assigned" Key="Assigned" AllowResize="Free" AllowRowFiltering="False"
AllowUpdate="Yes" Width="80px" Type="Custom" EditorControlID="assignTo" IsBound="false">
<Header Caption="Assigned To" ClickAction="SortSingle">
<RowLayoutColumnInfo OriginX="15" />
</Header>
<HeaderTemplate>Assigned To <select id="AssignToDefault" width="40px" runat="server" name="AssignToDefault"><option value="0">-Select-</option><option value="1">User</option><option value="2">API</option></select>
</HeaderTemplate>
<Footer>
<RowLayoutColumnInfo OriginX="15" />
</Footer>
</igtbl:TemplatedColumn>
I am trying to solve the issue since long. Please help.
Found the answer on Infragistics Community:
http://community.infragistics.com/forums/p/67149/340326.aspx#340326
EDIT (in case link deprecates):
I tested your scenario and was able to replicate the behavior in IE8 but not in Firefox.I suggest that you try disabling the activation behavior of the grid to see if that makes a difference:
UltraWebGrid1.DisplayLayout.ActivationObject.AllowActivation = false;
Alternatively you may want to consider using the WebCombo control in this scenario as it seems to be unaffected by the issue.
Please note that the UltraWebGrid control is now outdated and as of .NetAdvantage 2011 Volume 2 is no longer included in our product package. I would suggest that you consider switching to the WebDataGrid/WebHieararchicalDataGrid. More information regarding these controls is available at:
http://help.infragistics.com/NetAdvantage/ASPNET/2011.2/CLR4.0/?page=Web_WebDataGrid_WebDataGrid.html
Additional samples demonstrating the features of these grids can be found at:
http://samples.infragistics.com/aspnet/
Thank you :)

Resources