Apex : How to display an error on a page Item created dynamically?

送分小仙女□ 提交于 2020-06-17 13:25:11

问题


I'm running Apex 19.2

I have a page with some items created dynamically as follows :

HTML clob;    
Html := APEX_ITEM.textarea(p_idx=>32, p_value=>'MyValue',p_item_id=>'MyId',p_attributes=>'class="textarea"');   
htp.p(HTML);

The page items are generated correctly :

<textarea name="f32" rows="4" cols="40" wrap="VIRTUAL" class="textarea" id="MyId"></textarea>

I'm also adding the item wrapper to match the static Items layout created from the designer.

<div class="t-Form-inputContainer col">
    <div class="t-Form-itemWrapper">     
        <textarea name="f32" rows="4" cols="40" wrap="VIRTUAL" class="textarea" id="MyId"></textarea>
    </div>
    <span id="MyId_error_placeholder" class="a-Form-error"></span>                            
</div>

In the validation, I'm checking some rules from apex_application.g_fn arrays and I would like to show an error on the item created via :

apex_error.add_error(p_message => 'error', p_display_location => apex_error.c_inline_with_field_and_notif, p_page_item_name=> 'MyId');

After validation, the error is not shown next to the item created. Notification also appears but it's empty. However If I try to show the same error on a static item created in the designer. The error is shown properly.

Can anyone help please ? Thanks.


回答1:


As you've found, APEX_ITEM doesn't work with APEX_ERROR in the way that you'd like it to. Marc's comments here indicate that APEX_ITEM will likely not be developed further, so it probably never will. https://stackoverflow.com/a/61737128/3010084

Your best option might be to move your validation logic to a stored procedure. Do all the validation in one call via parameters. In addition to the regular parameters, add a parameter that indicates if the response should be JSON or not. If so, just return a JSON document with the errors, otherwise use apex_error. This will allow you to call the validation logic via Ajax to show the errors where you like, but also on submit/page processing (because client-side validation can't be trusted).

Here are some steps you can follow to see how this works... First, compile the following procedure in your schema:

create or replace procedure validate_thing(
  p_description in  varchar2,
  p_return_json in  boolean,
  p_json_result out json_object_t
)
is

  l_errors_arr    json_array_t := json_array_t();
  l_error_obj     json_object_t := json_object_t();
  l_item_id       varchar2(30);
  l_error_message varchar2(255);
begin

  if length(p_description) > 10
  then
    l_item_id := 'description';
    l_error_message := 'Description should be less than 10 characters.';

    if p_return_json
    then
      l_error_obj := json_object_t();

      l_error_obj.put('pageItem', l_item_id);
      l_error_obj.put('message', l_error_message);

      l_errors_arr.append(l_error_obj);
    else
      -- Server-side code will not worry about displaying the error with the item as 
      -- this is just a backup for the client-side validation
      apex_error.add_error(
        p_message          => l_error_message,
        p_display_location => apex_error.c_inline_in_notification
      );
    end if;
  end if;

  if p_return_json
  then
    p_json_result := json_object_t();

    if l_errors_arr.get_size() > 0
    then
      p_json_result.put('status', 'error');
      p_json_result.put('errors', l_errors_arr);
    else
      p_json_result.put('status', 'success');
    end if;
  end if;

end;

As you can see, the procedure has logic to do client-side validations (JSON) or server-side validation (APEX_ERROR). You would need to add additional parameters and logic as needed for the form.

Create a new blank page in your app and go to the Page Designer for the new page. Right-click Content Body (under Regions) and select Create Region. Set the region's Type to PL/SQL Dynamic Content and add the following code to the PL/SQL Code attribute:

declare

  html clob;

begin

  -- The div and fieldset wrappers are needed so that APEX will generate an error
  -- message template automatically to display the error inline.
  html := '<div><fieldset>';
  html := html || APEX_ITEM.textarea(p_idx=>32, p_value=>'MyValue',p_item_id=>'description',p_attributes=>'class="textarea apex-item-textarea"');
  html := html || '</fieldset></div>';

  htp.p(html);

end;

That code uses apex_item to add an item to the page dynamically. Note, the value passed to p_item_id, as that's important. The apex-item-textarea class is needed for error styling and the div and fieldset wrappers are needed to display error messages inline.

Select the Processing tab in Page Designer. Right-click Ajax Callback and select Create Process. Set Name to DO_VALIDATIONS and enter the following code in the PL/SQL Code field.

declare

  l_result json_object_t;

begin

  validate_thing(
    p_description => apex_application.g_x01,
    p_return_json => true,
    p_json_result => l_result
  );

  htp.p(l_result.to_string());

end;

That is the code that will call validate_thing with p_return_json set to true. Note that the value of "description" is being passed in via apex_application.g_x01. You have g_x01 - g_x20 to work within this way. There are various options you could leverage to sent values in via Ajax, this is just one example. See see the doc on apex.server.process (used next) for more info.

Return to the rendering tab, right-click the new region, and select Create Button. Set the Button Name to SUBMIT. Right-click the SUBMIT button and select Create Dynamic Action. Set the Name to SUBMIT clicked. Select the default Show action, set its Action to Execute JavaScript Code, then add the following code to the Code field:

apex.server.process(
  'DO_VALIDATIONS',
  {
    x01: $x('description').value
  },
  {
    success: function(result)  {
      apex.message.clearErrors();

      if (result.status === 'error') {  
        for (var idx = 0; idx < result.errors.length; idx++) {
          result.errors[idx].type = 'error';
          result.errors[idx].location = ['page', 'inline'];
          result.errors[idx].unsafe = false;
        }

        apex.message.showErrors(result.errors);
      } else if (result.status === 'success') {
        apex.page.submit('SUBMIT');
      }
    },
    error: function( jqXHR, textStatus, errorThrown ) {
      console.log(jqXHR, textStatus, errorThrown)
    }
  }
);

This is the JavaScript code that will invoke the new DO_VALIDATIONS Ajax process. If errors are returned from the server, apex.message.showErrors will display them. Otherwise, the page is submitted for processing.

Select the Processing tab, right-click Processing, and select Create Process. Set Name to Do Validations and enter the following code in the PL/SQL Code attribute:

declare

  -- Only needed to call validate_thing, not used.
  l_result json_object_t;

begin

  validate_thing(
    p_description => apex_application.g_f32(1), -- This is where the item's value will be when submitting normally
    p_return_json => false, -- This tells validate_thing to use apex_error
    p_json_result => l_result
  );

end;

That code will invoke validate_thing with p_return_json set to false. This will rerun the validations on the server-side to ensure they are enforced there. As it's just a backup for the client-side call, I don't worry about displaying errors inline with the items (the JS will do that).

Right-click Processing again and select Create Process. Set Name to Do Work and just enter null; for the PL/SQL Code Attribute. Set Success Message to It ran.. Under Server-side Condition, set Type to PL/SQL Expression and enter not apex_error.have_errors_occurred in the PL/SQL Expression field.

This process represents the actual business logic you want to run after validations have passed. You will only see the success message after clicking submit if both the Ajax and server-side validations have passed.

If you wish the test the server-side validations, add this line of JavaScript code in the Dynamic Action, just before the line that submits the page:

$x('description').value = '12345678910';

That will update the value of the text area to exceed the limit enforced by the server.



来源:https://stackoverflow.com/questions/61741878/apex-how-to-display-an-error-on-a-page-item-created-dynamically

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!