Apex:如何在动态创建的页面项上显示错误?

时间:2020-05-12 00:45:55

标签: oracle-apex

我正在运行Apex 19.2

我有一个页面,其中包含一些动态创建的项目,如下所示:

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

页面项目正确生成:

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

我还要添加项目包装器,以匹配从设计器创建的静态“项目”布局。

<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>

在验证中,我正在检查 apex_application.g_fn 数组中的一些规则,并且我想对通过以下方式创建的项目显示错误:

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

验证后,错误不会显示在创建的项目旁边。通知也会出现,但为空。但是,如果我尝试在设计器中创建的静态项目上显示相同的错误。错误显示正确。

任何人都可以帮忙吗? 谢谢。

1 个答案:

答案 0 :(得分:1)

如您所见,APEX_ITEM无法以您希望的方式与APEX_ERROR一起使用。 Marc在这里的注释表明APEX_ITEM可能不会进一步开发,因此可能永远不会开发。 https://stackoverflow.com/a/61737128/3010084

您最好的选择可能是将验证逻辑移至存储过程。通过参数一次调用即可完成所有验证。除了常规参数外,还添加一个参数,该参数指示响应是否应为JSON。如果是这样,只需返回带有错误的JSON文档,否则请使用apex_error。这样一来,您就可以通过Ajax调用验证逻辑,以在需要的地方显示错误,还可以在提交/页面处理中显示错误(因为不能信任客户端验证)。

您可以按照以下步骤查看其工作原理...首先,在架构中编译以下过程:

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;

如您所见,该过程具有执行客户端验证(JSON)或服务器端验证(APEX_ERROR)的逻辑。您将需要根据表单的需要添加其他参数和逻辑。

在您的应用中创建一个新的空白页,然后转到页面设计器以获取新页面。右键单击“ <内容>正文” (在“区域”下),然后选择创建区域。将区域的类型设置为PL / SQL动态内容,然后将以下代码添加到PL / SQL代码属性中:

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;

该代码使用apex_item将项目动态添加到页面中。注意,该值传递给p_item_id,这一点很重要。错误样式需要apex-item-textarea类,divfieldset包装器需要内联显示错误消息。

在页面设计器中选择“处理”选项卡。右键单击 Ajax回调,然后选择创建流程。将名称设置为 DO_VALIDATIONS ,然后在 PL / SQL代码字段中输入以下代码。

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;

这是将在validate_thing设置为true的情况下调用p_return_json的代码。请注意,“ description”的值是通过apex_application.g_x01传递的。您有g_x01-g_x20以这种方式工作。您可以利用多种选项来通过Ajax发送值,这只是一个示例。有关更多信息,请参见apex.server.process(下一个)中的文档。

返回渲染选项卡,右键单击新区域,然后选择创建按钮。将按钮名称设置为提交。右键单击 SUBMIT (提交)按钮,然后选择创建动态操作。将名称设置为提交单击。选择默认的显示操作,将其操作设置为执行JavaScript代码,然后将以下代码添加到“代码”字段中:

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)
    }
  }
);

这是JavaScript代码,将调用新的DO_VALIDATIONS Ajax进程。如果从服务器返回错误,apex.message.showErrors将显示它们。否则,页面将提交进行处理。

选择“处理”选项卡,右键单击“处理”,然后选择“创建过程”。将名称设置为执行验证,然后在“ PL / SQL代码”属性中输入以下代码:

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;

该代码将在validate_thing设置为false的情况下调用p_return_json。这将在服务器端重新运行验证,以确保在此处执行验证。因为它只是客户端调用的备份,所以我不必担心在项目内联显示错误(JS会做到这一点)。

再次右键单击处理,然后选择创建流程。将名称设置为执行,然后仅输入null;作为PL / SQL代码属性。将成功消息设置为运行。。在服务器端条件下,将类型设置为PL / SQL表达式,然后在PL / SQL表达式字段中输入not apex_error.have_errors_occurred

此过程表示验证通过后要运行的实际业务逻辑。如果同时通过了Ajax和服务器端验证,则单击“提交”后,您只会看到成功消息。

如果您希望测试服务器端验证,请在“动态操作”中,在提交页面的行之前添加以下JavaScript代码行:

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

这将更新文本区域的值,使其超过服务器强制执行的限制。