Adding suggestionItems Fails: "Cannot add direct child without default aggregation defined for control sap.m.SearchField" - sapui5

I am adding a SearchField with suggestions in the XML view. When I execute, I get the error
Error: Cannot add direct child without default aggregation defined for control sap.m.SearchField.
Please tell me what mistake I am making.
<SearchField
placeholder="final search"
tooltip="Search for datastore source names"
suggestionItems="{/records}"
selectOnFocus="true"
>
<suggestionItems>
<SuggestionItem
text="{dbname}"
description="{dbname}"
/>
</suggestionItems>
</SearchField>

Try to have a look to this example
sap.m.Input
suggestionItems="{/ProductCollection}" is the collection with all the available entries, text="{Name}" is one of the attributes of the collection item.
Check this example without search help https://sapui5.hana.ondemand.com/sdk/explored.html#/sample/sap.m.sample.InputSuggestionsDynamic/preview or https://sapui5.hana.ondemand.com/sdk/explored.html#/sample/sap.m.sample.InputSuggestionsCustomFilter/preview

You must be using an old UI5 version. The aggregation suggestionItems was introduced in 1.34.
Here, you can see that the app crashes throwing the same error if run with the version lower than 1.34: https://jsbin.com/qepojux/edit?html,js,output
To see with which UI5 version the app is currently running, press Ctrl+Left Alt+Shift+P.
See also Versioning of SAPUI5.

Related

Can we hide system default fields from workItem form?

Can we be able to hide the system defaults fields on the workitem form?
For TFS 2017, On-premises XML process model: You can modify select elements within the SystemControls section, such as changing the EmptyText attribute value for the System.Title field. In general, we recommend you don't customize this section much more than that. For example, you can't remove fields from or add other fields within this section.
For TFS 2018, On-premises XML and Azure DevOps Services, Hosted XML process models: You can specify the ShowEmptyReadOnlyFields attribute, or select to hide or replace select fields defined within the SystemControls section.
For example, to hide the Reason field, you modify the Control element with the Visible attribute.
<Control Label="Reason" Type="FieldControl" FieldName="System.Reason" Visible="false" />
To replace the Reason field with another field, use the Replaces attribute. Also, remove the entry for the Reason field from within the section.
<Control Label="Milestone" Type="FieldControl" FieldName="Fabrikam.Milestone" Replaces="System.Reason" />
See more info in the docs.
If the process you are using is a custom process inherited from the template process, normally you can't hidden the default fields.
If your process is defined using a XML process model, as #ShaykiAbramczyk suggested, you can try to edit the XML file for the process definition to hidden the fields.

SAPUI5 - How to change the table in the same View?

situation:
2 diferent tables, 1 view;
want to achieve:
I've got to change the table when I change the selectedKey in a select.
I already tried to create fragments with each table and call the one I want when I change the select.
fragment1 - table 1
fragment2 - table 2
select - oEvent (onChangeSelect) - getSelectedKey - if(key === 1) - call fragment1, if(key === 2) - call fragment2, but it gives me an error.
I don't know if this is correct and I'm not finding any infos related online.
If someone can show some links or give me just an idea on how can I do this, it would be perfect.
You could use the concept of binding to achieve this without coding. assume you have something like that in your view:
<Select><!-- ... --></Select>
<core:Fragment ... /><!-- table 1 -->
<core:Fragment ... /><!-- table 2 -->
First, add a model to your app, which will contain the information about the status of the app (which of the fragments is visible currently). Easiest way is to start with an empty JSON model. If you are familiar with manifest.json config, add it there. if not, you could add this in your Components init method:
this.setModel(new JSONModel(), "config");
This way, the new empty model is available under the name "config" in all the views of the app.
Now, we will add a visibility flag, which will control the visibility of your fragments (tables), and can be changed by the select:
<Select selectedKey="{config>/selectedFragmentKey}">
<core:Item key="" text="Please choose one" />
<core:Item key="showFragment1" text="Show Fragment 1" />
<core:Item key="showFragment2" text="Show Fragment 2" />
</Select>
This new version will store the key of the selected item in the config model in the path /selectedFragment. Add visibility flag to fragments (tables):
<!-- table 1 is only visible if "Show Fragment 1" was selected -->
<Table visible="{= ${config>/selectedFragmentKey} === 'showFragment1'}" .../>
<!-- table 2 is only visible if "Show Fragment 2" was selected -->
<Table visible="{= ${config>/selectedFragmentKey} === 'showFragment2'}" .../>
and you're done.
Main lesson here: learn to use bindings.
If I understood the question correctly, you have a selection control (which has 2 entries), and a table in the view. Based on the selection item, you want to display ONE of the tables at any given point of time. I am also assuming here, that the tables are purely used in the current view only & not really a "re-useable" thing - which gets used in different places of the app (which then renders the use of fragments an overkill).
I am assuming, both tables are bound (although to different data sets).
In that case, consider using the "visible" property of the appropriate table to "false".
Remember - all UI components, including tables inherit from sap.ui.core.Control - which has the "visible" property.
In API reference for table : https://sapui5.hana.ondemand.com/#/api/sap.ui.table.Table%23methods/Summary
If you scroll down to "Borrowed from:" section, you will see the "setVisible" and "getVisibe" methods.
So, in the event fired during selection change, you can grab the table control & set the visibility using the aforementioned methods.
Alternatively, you can also set an expression binding directly on the table control in XML, which evaluates to "true" or "false" (perhaps using a formatter).
Let me know if you need further info on this.
Best Regards,
Gopal Nair.

How to get id of invisible element in fragment?

I have a Dialog in fragment:
<core:FragmentDefinition
xmlns="sap.m"
xmlns:f="sap.ui.layout.form"
xmlns:core="sap.ui.core">
<Dialog title="{i18n>AddNewItem}" resizable="true" draggable="true">
<content>
<MessageStrip
id="failMsg"
visible="false"
text="{i18n>SensorTypesCreateFail}"
type="Error"
showIcon="true"/>
</Dialog>
</core:FragmentDefinition>
As in UI5 doc:
Retrieving a control instance when the fragment is not part of a view:
When no fragment ID was given: myControl = sap.ui.getCore().byId("myControl")
When a fragment ID myFrag was given: myControl = sap.ui.core.Fragment.byId("myFrag", "myControl")
If there is no visible="false", I can get this MessageStrip by sap.ui.getCore().byId("failMsg").
But I found that with visible="false", id of MessageStrip is sap-ui-invisible-failMsg, I failed to found proper API to get it.
Of course I can use sap.ui.getCore().byId("sap-ui-invisible-failMsg"), but I am not sure whether this ID will change after I deploy it to FLP, and as #schnoedel said in another question:
Beware that the prefixes like -- and --- used by the framework may change in the future. Thats why it's recommended to use the public api functions the framework supplies like byId() and createId().
So, is there any better way to get it?
Update:
Change my code from:
this[dialogName] = sap.ui.xmlfragment("namespace." + dialogName, this);
this.getView().addDependent(this[dialogName]);
To
this[dialogName] = sap.ui.xmlfragment(dialogName, "namespace." + dialogName, this);
this.getView().addDependent(this[dialogName]);
And now my id is sap-ui-invisible-dialogName--failMsg...
It depends on what you want to achieve after getting the ID. If you just want to change a property you could do it without any ID via a Model.
For that you can assign a Model field (i.e. baseModel>/visable) to the visable property and once it should be changed you change the model and via two way binding it updates the control.
code to change a model:
this.getView().getModel("nameOfUrModel").setProperty("property", "value")
for more information about this just check the walkthrough tutorial on
https://sapui5.hana.ondemand.com/
And if you for whatever reason really need the ID:
https://sapui5.hana.ondemand.com/#docs/api/symbols/sap.ui.core.Fragment.html
here you find the command:
sap.ui.core.Fragment.byId(sFragmentId, sId)
It should be able to return the Control your using
Hope that helps
Eric
You were very close to the solution. After adding dialogName for the fragment ID in its creation, you just have to call the API ...:
sap.ui.require(["sap/ui/core/Fragment"], Fragment => Fragment.byId(dialogName, "failMsg"));
... to get the control instance as mentioned here.
However, regardless whether you provided a fragment ID or not, you can easily ignore the render prefix "sap-ui-invisible-" at any time - Meaning that you could've also been able to get the control instance via sap.ui.getCore().byId("failMsg") instead of sap.ui.getCore().byId("sap-ui-invisible-failMsg") even if the control is invisible.

Auto populate form input based on name?

If I have a Command Object such as
class AppContactInfoCommand {
String fname = "Tom";
}
When I pass that command object to my view to populate my form I have to do this
<g:textField name="cmd.fname" value="${cmd.fname}"/>
This just seems extremely repetitive and time consuming if I have large forms with many fields. Isn't there any way to to have the g:textField intelligently detect that value and auto-populate the value field so all I have to do is
<g:textField name="cmd.fname" />
Other frameworks I have worked with do this so Im sure there must be a way from Grails to do this too.
Grails Version: 3.1
There is nothing stopping you from writing your own tag library to do just that. However the included tag libraries for such things as the textField do not have this behavior. As can be seen from the documentation.

how to disable swap in ion-slide-box in Ionic Framework

i want to disable swap in ion-slide-box so i added this
active-slide="slidestop($index)"
in ionic-slide-box as you can see below
<ion-slide-box show-pager="false" ng-repeat="test in demoQuiz" active-slide="slidestop($index)">
and added this in controller.js
$scope.slidestop = function(index) {
$ionicSlideBoxDelegate.enableSlide(false);
}
but i'm getting this error:(
Error: [$compile:nonassign] Expression 'slidestop($index)' used with directive 'ionSlideBox' is non-assignable!
although this code working fine:)
If you carefully see ionic Docs, you will find that
active-slide is an expression, which represents the Model to bind the current slide to.
You have written a method invocation inside the active-slide attribute, without returning anything from the method.
You can rewrite the stuff like this :
<ion-slide-box show-pager="false" ng-repeat="test in demoQuiz" active-slide="activeSlide">
Then, Inside your controller, you can write
$ionicSlideBoxDelegate.stop()
This will stop ionic slide box until and unless you explicitly change the slides.
More Details here