XPages Tip: Select a Working Set in Package Explorer (and Navigator)
If you’ve been using Domino Designer for any length of time, you’re likely aware that you can group your applications into Working Sets in the Applications view. But did you know that you can do the same thing in the Package Explorer and Navigator views?
Working Sets in the Applications View
Here’s what it looks like to select a working set in the Applications view in DDE:
You can choose one or select the Multiple...
option to select multiple working sets.
Working Sets in the Package Explorer View
Until recently, I didn’t realize that I could make a similar selection in the Package Explorer view. I always just saw it as annoying that I had to dig through every NSF I’ve worked on until I looked around for this option.
If you click on the icon with 3 horizontal gray lines, you get this drop-down:
You can select a single working set or choose the magic Window Working Set
option to have the Package Explorer databases automatically updated based on your working set selection in the Applications view.
If you want to disable this option and show them all, you can select Deselect Working Set
from the menu.
Working Sets in the Navigator View
Interestingly, you can also choose a working set in the Navigator view, but the options are more limited; there’s no option to link it up with the current working set.
XPages Tip: Fixing a partial refresh issue with the Pager Add Rows control in a Data View
I came across a strange issue with a Data View using a Pager Add Rows control resetting the number of documents displayed after a partial refresh. In this post, I’ll explain the scenario where I saw the issue and show the simple solution that fixed the problem.
The Problem
I have a Data View that starts with 20 rows and uses a Pager Add Rows control to add 10 more rows at a time.
Within the summary facet, there’s an action that can take place, which runs a minimal script and then performs a partial refresh with partial execution on the summary section.
This *seems* to be fine when performed within the first set of rows, but I noticed that if additional rows are added to the display and then the action is run in any one of the rows, the action runs successfully, but the data view is reset to only display the initial set of 20 rows.
If the action was taken on a row after the initial 20, I can add rows again and see that the action has taken place and the partial refresh has occurred as designed.
The Fix – Changing the ‘State’ Property
I tried making a number of changes to partial refresh and partial execution settings, but none of them fixed this issue.
Ultimately, the issue was fixed by a simple property change. The Pager Add Rows control has a state
property (All Properties > basics > state)
When set to true
, it stores the view state on the server.
This did the trick. It allows the row count to be preserved between partial refreshes by storing it on the server.
Monitor Source Control Synchronization with the Console View in DDE
If you’d like to monitor the synchronization of an application with the local source control repository, you can use the Console view in Domino Designer. In this post, I’ll show different kinds of helpful information that the view displays.
Console View
If you’re using source control, the Console view displays information about the synchronization of design elements between the NSF and the (source control) on-disk repository.
This can be helpful to see what’s going on if your DDE client is responding slowly (and may help you decide whether you want to enable or disable automatic synchronization). It may also be helpful in tracking down the creation of the dreaded .orig files.
Opening the Console View
Select Window
> Show eclipse views
> Other...
Under General
, select Console
Console Output
When you open an application in DDE, you’ll see the console start the synchronization process. (There’s even a misspelling to keep the grammar cops on alert.)
When you update an existing design element, you see that it exports the change to the on-disk repository (for the .xsp and related .xsp-config file).
When you add a new design element, it creates the .xsp, .xsp.metadata, and .xsp-config files in the on-disk repository.
Automatic Synchronization
If you have automatic synchronization enabled, it will happen when the application is built. (If you have Build Automatically enabled, it will happen automatically. Otherwise, it’ll happen when you build the application.)
These two properties in the Domino Designer preferences determine whether synchronization is automatic:
Simple Sync Conflicts
If you’ve seen a popup like this, then there is a synchronization conflict:
Here’s the corresponding message in the Console view:
Nsf file AppProperties/database.properties and disk file AppProperties/database.properties both have been updated since last sync or are never synced:Wed Aug 20 20:17:36 EDT 2014
It indicates a conflict and it’s making it easy for you to choose how to resolve it. You can also see evidence of this in the Console view. I tend to see this often with the database.properties (because the time stamps are always being modified). This type of popup is displayed when you synchronize with source control before opening the application in DDE. (If you modify the same element as someone else, conflicts will show up differently when you try to commit changes within your source control plugin or application.)
One View – Multiple Uses
The Console view is displayed as Console (DDE Sync Console) when displaying source control sync information. You can also switch it to be used as a Java stack trace console by via the Display Selected Console icon.
Computing Custom Date Format Patterns Throughout an Application
If you want to ensure consistency in date formatting throughout your application, you can define the pattern for each Edit Box or Computed Value control that displays a date. What you may not have considered is that you can compute the date format, so you can define it in one place and use the same format everywhere. In this post, I’ll show how you can set it up and even change it conditionally.
Locale Conversions
The browser will automatically attempt to format dates based on your specified locale. Here’s an example of a computed field set to display a date. The Display type
must be set to Date/Time
.
Here’s how it displays in my browser when the language is set to English:
Here’s how it displays when I change my browser language to French:
Custom Date Patterns
If you want to change the default formatting, you can define a custom date format pattern.
To define a specific pattern, change Display format
to Custom
and then you can edit the Pattern
field. (You can select a pre-defined pattern or enter your own.)
In this case, the pattern will stay the same, regardless of the browser language.
(Note: When defining a date pattern, the month value uses one or more capital M’s, because the lower case m is for minutes when defining a time pattern.)
Computing Date Patterns
Just like most other properties in XPages, there’s a blue diamond next to the Pattern
field, allowing you to use SSJS to compute it. This gives you the opportunity to create a library function to return some pattern to use. Then, you can set all of your date controls to call the same function and modify the pattern in one place.
Your library function could be as simple as this:
function getDateFormat() { return 'dd-MMM-yyyy'; }
Taking it one step further, you could add logic in the function to conditionally determine the pattern, whether it be based on a user preference or a locale or just changing date formatting patterns on a daily basis because you like to mess with your users.
If you use more complex logic, you may also want to consider storing the pattern in an applicationScope
variable, so it’s available throughout the application.
function getDateFormat() { if (!applicationScope.dateFormat) { // Logic to determine date format applicationScope.put('dateFormat', some_date_format); } return applicationScope.dateFormat; }
Computation Timing
The default setting for the logic Compute Dynamically
(#). If you leave it that way, it will throw this error when you load the page: The value of the property pattern cannot be a run time
binding.
To fix this, select Compute on Page Load
when entering/editing the snippet or change the octothorpe/pound sign/hash (#) to a dollar sign ($) in the page source, because date pattern computations only work on page load.
Quick Replace
If you’ve already set up hard-coded patterns on date fields, they would look something like this:
You can do a quick search and replace to modify them all easily.
Search for:
pattern="dd-MMM-yyyy"
Click the Replace...
button rather than the Search
button.
Then replace with:
pattern="${javascript:return getDateFormat();}"
XPages Tip: Control Declaration Snippets
Control Declaration Snippets give you an easy way to retrieve a properly-typed handle to an XPages control on your page. In this post, I’ll show how to use them and why they are beneficial.
Control Declaration Snippets
From the SSJS script editor, Control Declaration Snippets is one of the Libraries:
options on the Reference
tab.
It displays an alphabetized list of controls on the page.
Double-click any one to insert the control declaration snippet into your script.
This screen shot shows the result of adding snippets for all 7 controls on my sample page:
Benefits
This is a convenient way to save a few keystrokes in setting up a handle to a control on your page, but that’s not the only benefit.
Normally, when you set up a variable for a handle to a control, you don’t enter the full data type of that control. Control declaration snippets do that for you. The big advantage is that typed variables provide better typeahead.
Take, for example, these two lines, which accomplish the same thing:
var myInputText = getComponent("inputText1"); var inputText1:com.ibm.xsp.component.xp.XspInputText = getComponent("inputText1");
If you type myInputText.
you’ll get some typeahead options because the editor knows that you’re dealing with a some component.
However, if you type inputText1.
you’ll get many more typeahead options (including event handlers) because the editor now knows exactly what type of component that you’re working with.
Set Focus on a Field when Showing a Bootstrap 3 Modal
While testing an application that I’m working on, I noticed that the focus is not set on a field within a Bootstrap modal when it’s shown. This is annoying to the user because it requires to tab a number of times (since the focus stays on the button clicked to show the modal) or click into a field in order to start typing. In this post, I’ll show how to force the focus to be set on a specific field when a modal is shown.
Event Delegation
One simple approach is to use jQuery event delegation (here’s a great explanation from Mark Roden). An event handler can be added to the body tag to fire whenever a modal is shown. Within that handler, we can set the focus on a specific field.
$('body').on('shown.bs.modal', '.modal', function () { $('[id$=myField]').focus(); })
The first line sets up the event delegation by adding a listener to the body of the page for the event of showing a modal (shown.bs.modal
). The second line locates the field named myField
and sets focus on it.
The selector in the second line may look a bit strange, but it’s effect is to find the element where the id
attribute ends with myField
. This is because XPages adds a number of colon-separated prefixes to each element, depending on it’s depth in the page structure. In order to not worry about all of that, the code looks for the element that ends with the name that I assigned to the field.
Here are two other options that you have for achieving the same effect:
- Add a unique class name to the field and use $(‘.yourClassName’) as the selector
- Use Mark Roden’s x$() function to select an element
Modals and Partial Refreshes
As if there haven’t already been enough (too many?) references to Marky, take a look at this post if you have a modal that needs to perform partial refreshes.
Ultimately, the code I’m actually using in my application looks like this:
$('body').on('shown.bs.modal', '.modal', function () { $('FORM').append($('.modal')); $('[id$=myField]').focus(); })
Multiple Modals
This method works fine on a page that only has one modal. If you have multiple modals, you’d need to adjust the logic in order to set the field focus as desired. One more generic option would be to change the jQuery selector to just find the first input field on the modal.
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:
If I clear the value in the field and tab out of it, I am presented with this error message: ‘This value is required’
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.
This does the job and it changes the attribute in the HTML output for the page to: aria-required="false"