Archive | Form RSS for this section

XPages Tip: Disabling Required Validation in a Dojo Filtering Select

Dojo Filtering Select (xe:djFilteringSelect) controls include client side ‘required’ validation by default. The problem is that if it fails this validation, any page submission or other server-side action will not be triggered. However, if you want to disable this validation, the built-in property of the control doesn’t work. In this post, I’ll show how to achieve the desired effect.

Creating a Filtering Select

If you’re not familiar with the Dojo Filtering Select, take a look at this post.

Validation Behavior

Take, for example, the Dojo Filtering Select that I used in a recent post about changing the search behavior of a Dojo Filtering Select:

FilteringSelect_Required-1

If I clear the value in the field and tab out of it, I am presented with this error message: ‘This value is required’

FilteringSelect_Required-2

The problem is that any server-side onChange error handler of the field will not fire because the field failed client-side validation.

Disabling the Required Validation

The Dojo documentation shows that adding a required attribute and setting it to false will disable this behavior.

There’s a required property on the djFilteringSelect control. Unfortunately, it has no effect when set to false.

If you look at the HTML output, you’ll see that the field has this attribute: aria-required="true"

To get it to work, you can add the required attribute (and set it to false) as a Dojo attribute.

FilteringSelect_Required-3

This does the job and it changes the attribute in the HTML output for the page to: aria-required="false"

Advertisements

XPages Tip – Disable Autocomplete on All Fields via the Theme

In my last post, I showed how to disable autocomplete on a single field. In this post, I’ll show how to disable it application-wide via the theme.

If you want to prevent autocomplete on all fields in your application, you can do it in one fell swoop by adding this code to your theme:

<!-- Set all edit box controls to disable autocomplete -->
<control>
  <name>InputField.EditBox</name>
  <property mode="override">
    <name>autocomplete</name>
    <value>off</value>
  </property>
</control>

This will automatically insert the autocomplete="off" attribute into all Edit Box controls in the application.

Here’s an example of what a field now looks like in the browser page source:

<input type="text" id="view:_id1:AutoComplete" name="view:_id1:AutoComplete" autocomplete="off" class="xspInputFieldEditBox"><br>

XPages Tip – Disable AutoComplete on a Field

Browsers will often remember values that you enter in fields and provide typeahead/autocomplete functionality for you when using fields with those same names in the future. This is also true of fields on your XPages forms by default. In this post, I’ll show you how to disable this on an input text control.

Disabling autocomplete is a very simple change to make. Just select your input control, go to All Properties and set the autocomplete property (under basics) to off.

AutoComplete1

To test the property, I created a simple page that has two fields bound to a form. I left the first field alone, but I set autocomplete to off on the second field. I submitted the form a number of times, entering ‘Name1’ into both fields, then ‘Name2’, and so on.

After several rounds of this, when I type an ‘N’ into the first field, I got a typeahead list of all of the values that I had entered that began with the letter ‘N’.

AutoComplete2

However, in the second field, even though I entered all of the same values as the first field, there was no typeahead.

AutoComplete3

XPages Tip: Fixing the Display of Comboboxes, Radio Button Groups, Checkbox Groups, and Listboxes in Read Mode with Dojo

With a couple of minor adjustments to the code shown in a previous post, I now have a script that will fix the display of comboboxes, radio button groups, checkbox groups (single or multi-valued), and listboxes (single or multi-valued) all in one fell swoop!

The output of a single-value for any of these field types looks like this:

<table id="id">
  <tr>
    <td>value </td>
  </tr>
</table>

However, if you have a field with multiple values, it separates each value out into its own row, so the previous code needed to be adjusted to read the values out of all cells in the nested table. This code will concatenate multiple values to be separated by a comma and a space, but you can easily change that by modifying the code below.

<table id="id">
  <tr>
    <td>value 1</td>
  </tr>
  <tr>
    <td>value 2</td>
  </tr>
  <tr>
    <td>value 3</td>
  </tr>
...and so on...
</table>

This code, when run onClientLoad of the page, will fix all of these fields types, by replacing the table with just the value of the field, concatenating multiple values as needed.

if("#{javascript:document1.isEditable()}" == "false"){

  dojo.query('table td table[id]').forEach(function(node) {
    var value = '';

    // Get the value out of all cells in the nested table and concatenate them
    dojo.query('td', node).forEach(function(innerNode) {
      value += innerNode.innerHTML + ', ';
    });

    // Replace the table with only the value(s) (or a blank), but cut off the trailing comma
    node.outerHTML = value.substring(0, value.length-2);
  });
}

Line 1 tells it to only run in read mode. (Update the name of the document data source variable if you need to.)

Line 3 gets a handle on tables with ids that are nested inside of table cells.

Lines 7-9 search for all table cells within the table and retrieve each cell’s innerHTML, which contains a value. If there is no value, then there won’t be a table cell and it will replace the table with an empty string.

Line 12 replaces the nested with just the value that needs to be displayed.

And now the output from the example shown above looks like this, as it should:

If you run into conflicts with this affecting other tables in your page, you may need to refine the selector in line 3.

If you need to preserve the of the element and/or wrap it in a span tag like other field values, you can tweak the code accordingly.

XSnippet

The latest version of the code is posted as an XSnippet on OpenNTF

XPages Tip: Fixing the Display of Radio Button Groups in Read Mode with Dojo

In my last post, I showed a script that can be used to fix the display of combo boxes in read mode. As it turns out, the same code will fix radio button groups, because the output is the same!

The same code will also fix the display of single-value checkbox groups and listboxes. It will not properly handle multi-valued checkbox groups or listboxes, so I’ll be working on that next.

I have updated the comments on the XSnippet accordingly.

XPages Tip: Fixing the Display of ComboBoxes in Read Mode with Dojo

There’s a quirk with the display of combobox values when XPages are in read mode. Instead of just displaying the value, it generates a table with one row and one cell. This can cause problems with your form alignment if your fields are aleady in a table (especially a OneUI form layout table). This post contains a few lines of dojo code that can be used to fix the problem.

If you have a one-row two-cell table that contains a label and a combobox, it looks like this in the page source in Domino Designer:

<table>
  <tr>
    <td>
      <xp:label value="Label" id="label1" for="comboBox1"></xp:label>
    </td>
    <td>
      <xp:comboBox id="comboBox1" value="#{document1.Field1}">
        <xp:selectItem itemLabel="Value 1"></xp:selectItem>
        <xp:selectItem itemLabel="Value 2"></xp:selectItem>
        <xp:selectItem itemLabel="Value 3"></xp:selectItem>
      </xp:comboBox>
    </td>
  </tr>
</table>

But this is the output in read mode:

<table>
  <tr>
    <td>
      <label id="view:_id1:label1" for="view:_id1:comboBox1" class="xspTextLabel">Label</label>
    </td>
    <td>
      <table id="view:_id1:comboBox1">
        <tr>
          <td>Value 1</td>
        </tr>
      </table>
    </td>
  </tr>
</table>

Instead of just writing out the value of the combobox, it wraps it in a table.

(A regular field value is generally written out within a span tag that has the id of the control.)

When the combobox doesn’t have a value, then an empty table is inserted (no rows or cells):

<table id="view:_id1:comboBox1"></table>

This code, when run onClientLoad of the page, will fix this issue by replacing the table with just the value of the combobox.

if("#{javascript:document1.isEditable()}" == "false"){
  // Search for all nested tables with ids
  dojo.query('table td table[id]').forEach(function(node) {
    var value = '';

    // Locate the first table cell, which contains the value
    dojo.query('td:first-child', node).forEach(function(innerNode) {
      value = innerNode.innerHTML;
    });

    // Replace the table with only the value (or a blank)
    node.outerHTML = value;
  });
}

Line 1 tells it to only run in read mode. (Update the name of the document data source variable if you need to.)

Line 3 gets a handle on tables with ids that are nested inside of table cells.

Lines 7-9 search for the first cell within the table and retrieve it’s innerHTML, which is the value of the combobox. If there is no value, then there won’t be a table cell and it will replace the table with an empty string.

Line 12 replaces the original combobox table with just the value that needs to be displayed.

And now the output from the example shown above looks like this, as it should:

<table>
  <tr>
    <td>
      <label id="view:_id1:label1" for="view:_id1:comboBox1" class="xspTextLabel">Label</label>
    </td>
    <td>
      Value 1
    </td>
  </tr>
</table>

If you run into conflicts with this affecting other tables in your page, you may need to refine the selector in line 3.

If you need to preserve the of the element and/or wrap it in a span tag like other field values, you can tweak the code accordingly.

Readers and Authors Fields in XPages

You can create readers and authors fields on your form data source behind an XPage, but it won’t automatically store the data in the fields correctly. Use the code below to set the field types properly when you save your document.

As far as I’ve seen, there isn’t a way to tell an XPage core control specifically for an Authors or Readers field. When you save a new document, it will just save them all as plain text fields.

Here’s a screen shot of the properties of an Authors field on a document that I created from a simple XPage:

AuthorsFields1

The same thing applies to a Readers field.

To fix this, you just need to add code to get a handle to the items on the back-end document and set the type. It only needs to run the first time the document is saved, so use code like this before you save the data source:

if (document1.isNewNote()) {
	var docBackEnd:NotesDocument = document1.getDocument();

	var item:NotesItem = docBackEnd.replaceItemValue('AuthorsName', getComponent('authorsName').getValue());
	item.setAuthors(true);

	item = docBackEnd.replaceItemValue('ReadersName', getComponent('readersName').getValue());
	item.setReaders(true);
}

Now, when the document is saved, the type is set properly.

AuthorsFields2

There are several variations on this theme. The code I have above may seem strange that it’s setting the values on the back end fields directly. It would seem that you should just be able to use something like this:

var item:NotesItem = docBackEnd.getFirstItem('AuthorsName');

However, in this simple example, I’m executing this SSJS code before the document has been saved, so the item doesn’t exist yet and an error is thrown.

You could, instead, run code with the getFirstItem() method on the postSaveDocument event of the document data source. The item would already exist at that point, but you’d need to save the document again, so you’re adding that overhead, plus the need to check the field type so you don’t update it on every save thereafter. (You also need to remove the isNewNote() check, because it will never return true at that point!) It just depends on where you’re triggering your code, whether it’s from a button or from a form event. I find the first method much easier to manage.

Another alternative is using the Compute With Form option of the data source, but that is not ideal, because it adds processing overhead (on every save) and leads you into the bad habit of leaving form logic on the underlying form, making it more difficult to troubleshoot and maintain.