Is custom control loaded property working correctly? - xpages

What I want to do is create a custom control that determines on it's own, if it should be loaded or not. So I looked at the loaded property for the custom contol but it does not work the way I expected. It at least seems to be ignoring this property. I put together a little test control to demonstrate.
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" pageTitle="Test" loaded="false">
This is a test custom control.
</xp:view>
The control is always displayed even though it's loaded property is set to false. Nw what I can do is to place the custom control on my page and set the loaded property there. That works fine but I would like to avoid having to set that property every time I use the control. I would like to put the code in the control to see if it should be loaded or not.
Am I missing someting?
Yes I know I can put everything inside a div on the control and not load the div but I would simply rather not load the control at all, if it is not supposed to be loaded.

I'm not entirely sure why the loaded attribute is even available on the root element, because what it does is inherently impossible to evaluate at that level.
As opposed to rendered, which determines whether any representation of the component will be sent to the consumer, loaded determines whether or not the component is even created. So if rendered is false, it just doesn't display... if loaded is false, it doesn't even exist. The component needs to exist for the view tag attributes to be evaluated, so it's too late by then to stop it from existing since it needs to exist in order to be told not to exist.
As a result, in order to use loaded to suppress the entire control, the attribute needs to be set on the control reference. In other words, when adding the control to an XPage (or another custom control), set a loaded expression on the tag for the control. If it evaluates to false, then the control will never be loaded.
Remember, all of this ends up executing as Java... if you block construction of a class instance, you don't have a class instance to ask whether it should have been constructed. Conversely, if you create a class instance, then ask it whether it should exist... too late, it already exists. If the custom control should own the logic for whether its contents should exist, then specifying that logic in the loaded attribute of a single child container is the "right" approach.

Related

How to know when a property has been updated from it's connected attribute?

Given:
#property({type: Boolean, attribute: 'some-attr'}) someAttr = false;
I was expecting to see updated being fired once 'some-attr' value gets updated in the DOM.
However, updated doesn't get fired at all.
Is my expectation wrong, or should I set things up differently?
Looking at Elm's discussion of properties vs attributes, the documentation of the Html.Attributes module's attribute function, and the Elm documentation on custom elements, I am pretty sure, that this is caused by simply binding an elm expression to attribute some-attr of the LitElement based custom element. I.e. the DOM attribute will always be present and hence the corresponding property always be true.
The default converter for Boolean (activated by providing type:Boolean to the decorator) mimicks the behaviour of HTML attributes used as flags (e.g. disabled on an <input> element): If the attribute is present (no matter the value), the flag is set (true). The implementation is really straight forward, if you want to look at it in the sources: https://github.com/Polymer/lit-element/blob/master/src/lib/updating-element.ts#L163
I see these options for your problem:
Implement some extra logic in Elm to add / remove the presence of the attribute.
Create your own attribute converter for the LitElement based custom element.
Use another default converter (e.g. for String, the "default" default converter) and implement the custom logic inside the LitElement (e.g. using a derived value).
Of these 3 options, I would generally recommend the first one, as your custom element then still behaves naturally, i.e. if some-attr should be a flag (boolean attribute), then following which HTML semantics, it should be defined by its presence, not its value. This allows you to re-use it in other projects without surprising other developers.
That being said, there may of course be project-specific requirements, that are more important. E.g. if you only use this custom element in this one project with Elm, your road to success may be faster going for options 2 or 3.

Is it possible to disable all the inputs from a page with VueJS and BootstrapVue?

I have multiple buttons and form inputs in one page. All these buttons and form inputs need to be disabled or enabled depending on a condition.
I know that it is possible to use the disabled keyword inside a tag to disable a specific input or button. Also, I can just add the code
:disabled="true"
to disable the inputs depending of the boolean value of a variable.
However, this solution is not acceptable for me, since I will have to add this line of code to every inputs on my page (I may create new pages in the future, containing as many inputs).
I would like to know if there's a way that allows me to simply disable the parent container of all the inputs so that the children item (the inputs) are disabled.
If you inspect the Vue instance itself of the VM when running your code you can have something like this when you console.log(this),
It will give you output similar to this if you use the correct scope:
{
$attrs
$options
.......
$el
}
Inside $el there's object properties for accessing firsElementChild, previousElementChild, previousElementSibling, etc. There's a lot of HTML related properties, however, accessing HTML element this way can get messy pretty fast. I think that your best solution is the one you already mentioned or changing the CSS class dynamically.
If you use v-if to conditional render on a parent you can achieve pretty similar functionality too.
See: Conditional rendering

How to interact with control properties after a call to a managed action?

I have a managed action with returns bool when a button is pressed.
Depending on if true / false is returned I want to be able to change the properties of controls on the dialog. Not limited to just the text value.
Is this possible, for example the visibility, etc?
It is possible, however you will have to make sure there is a set-property control event (after your managed code custom action do-event) that touches a property related to anything you want the UI to update. If you change a property value within the managed code, or via the wrapper InstallShield provides, the Windows Installer UI doesn't track the change and update in response.
So, for example, you could wire your return value to the property RETURNVALUE, and then add a control event that sets better named properties like MYCONTROLTEXT or SHOWMYCONTROL; the control or its conditions would be wired to those better named properties.

Xpages add a custom control that doesn't take up space (rendered versus loaded versus visible)

I have some custom controls that I want to include in Xpages, but I don't want them to be visible to the user or to take up space on the screen, as it is throwing my alignment off. I have looked at the properties rendered, loaded, and visible, but I don't really understand them and they don't seem to do what I want, which is to include some functionality but not change the layout.
I am sure there is a way to do this, but I can't figure it out.
Loaded means it won't be added to the component tree and only affects server-side functionality. Because it's not in the component tree (the server-side map of the page) it can't be passed to the browser or processed during partial refreshes. Rendered and visible are the same and mean they're in the component tree, so server-side processing can interact with them, but no HTML is passed to the browser for them. So you can't interact with them via CSJS. If you want it passed to the browser, available for CSJS but not visible to the user, you'll need to set the style as display:none. Another option is to put that style in a theme and allocate the themeId you choose to your custom control.

Is there a way to use a javascript object as a custom control property?

I'm currently building a custom control to be used as an application's view navigator (classic OneUI style). First of all: this is a 8.5.3 based project, and unfortunately there's no way to use Extlib stuff or other extensions / plug-ins. So we have to build all the tricky stuff ourselves using only what came "out-of-the-box" with 8.5.3.
I'd llike to build my navigator using a repeat control containing <xp:link> controls. Datasource could be an array of javascript objects where each single object would look like this:
var navEntry = {"entryLabel" : "label-of-link",
"entryTarget" : "target-url-of-link",
"entryStyle" : "style-to-emphasize-selected-link"}
Each array element then would describe a single navigator entry.
Since the navigator will be used in all possible "DominoView" Xpages it yould make sense to build the array of JS objects at the Xpage level and then pass that info into the custom control.
I'm aware that there are multiple ways to do this, and one could be "Custom Control Properties". If there was a way to pass my JS object array.
(Hope I could make clear what I'm trying to do here...)
That object looks like a HashMap to me really. You should be able to pass that in to a custom control via custom property if you use the type java.util.HashMap I'd think. You'll need to type it in I'm sure. I've passed custom objects in by using java.lang.Object.
The custom control will get loaded during the Page Load event, and usually properties have to be available at that point. If they're loaded during the Render Response phase, that's too late. So your SSJS object will need to be Compute on Page Load.
To use contents of a repeat control, you would need to set repeatControls=true, otherwise the repeat is only built during render response. Until then it's just a single set of controls with no data in them. However, Im pretty sure repeatControls="true" means you only get the number of rows you define. You can't change it via a pager.
You can manually define the type of the custom property. For a standard SSJS Object you use "com.ibm.jscript.std.ObjectObject", for a SSJS Array you use "com.ibm.jscript.std.ArrayObject" etc. As editor for the custom property, I set the string editor ("String value").

Resources