lit-element bind to properties of an object that may be null or its subproperties may be null - lit-element

I have this scenario all the time: a list of entities (say Customer) and a form to edit the selected entity. I bind the form fields to properties of the currently selected entity like this:
<some-element value="${this.selectedCustomer.name}"></some-element>
This works as long as I have a selectedCustomer which is not always the case. When I don't have one, the form is supposed to be blank. I figured that the ternary operator could be used like this:
<some-element value="${this.selectedCustomer ? this.selectedCustomer.name : ''}"></some-element>
But then the problem goes on with the name property which might be null (looks artifical with Customer entities but is very important for me with nullable properties!). I can fix that with the ternary operator again:
<some-element value="${this.selectedCustomer ? (this.selectedCustomer.name ? this.selectedCustomer.name : '') : ''}"></some-element>
And this had to be done for all form fields for all entities. I just want ask for any experience whether this is the best way to do it?

Because lit-html expressions are just JavaScript, you have to do error handling as you would do in any other plain JavaScript. In this case you need to guard against undefined and there's nothing lit-html can do about that because it never sees the expression, just the resulting value.
As pointed out in the comments, JavaScript itself has addressed this now with the optional chaining and nullish coalescing operators:
You last example can now look like this:
html`<some-element value=${this.selectedCustomer?.name ?? ''}></some-element>`
This is supported in Chrome, Firefox, Edge, Babel, TypeScript and should be coming soon to Safari.

Related

Xpages Null or empty string

I am working with xpages components and it is hard for me to quess when the getComponent("comp").getValue() returns null or when returns "" (empty string).
Is there a way to tell? Are there components which return null when other components return ""?
A component will have a null value if the value property has not been assigned. That can happen if the it's bound to a field on a document and that document does not yet have the field, e.g. it's a brand new document. It can also happen if it's bound to a scoped variable that hasn't been set yet.
It's best practice to bind, wherever possible, to the data source rather than go via the component. This way document1.getItemValueString("myField") will return a blank string if myField hasn't been set on document1, as well as if myField's value is "". Also, if in the future youo delete the component comp, the compiler won't (and can't) tell you you're calling that component in SSJS and you'll get a runtime error. If you're using document1.getItemValueString("myField"), it will still work.
Plus, as Tim Tripcony said, it's slower https://twitter.com/timtripcony/status/359532216382001152 and this blog post goes into much greater depth on why to talk to data not components http://www.timtripcony.com/blog.nsf/d6plinks/TTRY-942UPQ

SPServices GetListItems returning field values as "undefined"

I ran across a problem for which I found no documented solution, but inadvertently found the solution myself. So I wanted to document this here for others who may encounter the same problem.
I was using a CAML query within SPServices to retrieve list items, then referencing "ows_{fieldname}" as usual to retrieve the field value for each list item. The field value was reported as "undefined" for all items. I quintuple-checked that I was specifying the proper name of the field and that my query was properly constructed.
I eventually discovered that the fields I was trying to reference were not displayed in the default view of the list. As soon as I changed the list properties to include the fields in the default view, the proper field values were returned within my javascript.
I don't know how much of Sharepoint's underpinnings work, but I was very surprised at my finding because it implies that the SPServices GetListItems method gets its data from the list's default view, not the actual underlying list. I realize I could be wrong in this interpretation, but I imagine others could run into this same problem.
The default, although unreliable, way GetListItems works is that it's suppose to returns all fields displayed on the default list view if you don't specify ViewFields on input. This is unreliable. Although you got it working - now - someone could come along later and change the default view thus breaking your sweet customization. Bummer. :)
I suggest always listing the ViewFields you are interested in on the GetListItems method. This ensures that your will get them if they are set. That's right. You could still get rows with an undefined field. This happens mostly on fields of type Lookup that are not set on a row.
Hope this helps you understand what is going on. Over the years I have created my own wrappers around SPServices to ensure I get back a reference to all fields requested, even if they are not in the response by Sharepoint.
When using SPServices' GetListItems method, be sure that any fields that you reference from the list are included in the list's default view, otherwise an undefined value will be returned.

Can i get all components of an xsp document in xpages?

I have a simple document with 3 fields and 1 rich text field. I also have an xpage with 3 simple edit box controls and 1 rich text. The name of my NotesXSPDocument is document1.
Question 1:
Can i get a vector with all the controls of the xsp document? for example, instead of using getComponent("fld1"), getComponent("fld2") ... etc, can i use something like getAllComponents() or document1.getControls()? These methods do not exist of course so i am asking if there is a way to do it. I know i can get all items of a document (not XSP) by calling document1.getDocument().getItems(). IS there anything similar for xsp?
Question2:
Lets say we can get a vector as i described above. Then if i iterate through this vector to get each control's value, is there a method to check if it is rich text or simple text field?
Technically, yes, but not readily and this is one of those situations where there's likely a better way to approach whatever underlying problem it is you want to solve.
Nonetheless, if you're looking to get a list of inputs on the page, XspQuery is your friend: http://avatar.red-pill.mobi/tim/blog.nsf/d6plinks/TTRY-96R5ZT . With that, you could use "locateInputs" to get a List of all the inputs on the page, and then check their value method bindings to see if the string version is referencing your variable name. Error-prone and not pretty, but it'd work. Since they're property bindings, I don't think the startsWith filter in there would do what you want.
Alternatively, you could bind the components to something in a Java class from the start. I've been doing just such a thing recently (for a different end) and initially described it here: https://frostillic.us/f.nsf/posts/my-black-magic-for-the-day . The upshot is that, with the right cleverness for how you do your binding="" property, you could get a list of all the components that reference a property of a given object.
As for the second part of the question, if you DO get a handle on the components one way or another, you can check to see if it's a rich text control by doing "component instanceof com.ibm.xsp.UIInputRichText".
A bit complex but yes. facesContext.getViewRoot() is an UIViewRoot object so it has List<UIComponent> getChildren() method which returns its children.
However, since it's a tree-structure, some of its children will have additional children components. You have to traverse the entire tree to build a list of components you want to see.
For types, you can decide what type a component is by its class. For instance, UIInput is a text box, etc.

Castor Marshaller to return empty tags for null objects

We are using Castor to unmarshall the Castor object to XML string. Castor is not generating Empty tags for null objects. Is there a API available to set it as parameter while unmarshalling?
There is a way to handle it by using the handler and override convertUponGet method to return empty string. But, Is there a better to do it?
Any clues will help.
From what I have seen there are 3 ways of dealing with this in order of best to worst.
Use a GeneralizedFieldHandler as explained in http://stackoverflow.com/questions/9176479/how-to-tell-castor-to-marshall-a-null-field-to-an-empty-tag. The field handler is reusable for other fields and doesn't change the behavior of your class.
Modify your get method for the given field to check for nulls and return an empty string if it is null. This approach changes the behavior of your class so if you have other parts of your code relying on nulls for this field, which also isn't a good idea, you will run into problems.
Modify Castor yourself to return an empty string when a null is encountered. Usually a really bad idea changing a tool you are using, unless you submit it back to the developers of the project to integrate into their code base for future releases. This doesn't seem likely since this issue was brought up back in 2007 http://old.nabble.com/Forcing-marshalling-of-null-empty-values--to9080721.html#a9096375 if not earlier

Siebel read only field problem

I'm trying to make a field read only when a given value is selected from a PickList.
I'm using a flag that is set to Y when the list has that value, and N otherwise.
I created a Business Component User Prop with the name Field Read Only Field: MyField set to the flag.
Thing is, this works with the vanilla component but it wont work on my custom component.
I can't figure out what is going on, the properties of the fields and flag are exactly the same. It should work...
Thanks for any help you can give me.
That user property is only supported on the business component class CSSBCBase and its subclasses. My guess is that you probably used CSSBusComp as the class of your business component. CSSBusComp is actually a superclass of CSSBCBase, and is very minimal and does not support Field Read Only Field. If that's the case, change it to CSSBCBase and you should be good to go.
Other option is that- if the record become read-only when the picklist value is being selected- that you'll need to make the picklist field Immediate Post Changes to be sure the user property is triggered.

Resources