How to set SinglePlanningCalendar's initial selected calendar view in XML? - sapui5

I want to use the sap.m.SinglePlanningCalender association selectedView to set the default selected View when a user starts the app:
<SinglePlanningCalendar selectedView="workWeekView">
<views>
<SinglePlanningCalendarDayView id="dayView" key="DayView" title="{i18n>calendarTabMyDay}" />
<SinglePlanningCalendarWorkWeekView id="workWeekView" key="WorkWeekView" title="{i18n>calendarTabMyWorkingWeek}" />
<SinglePlanningCalendarWeekView id="weekView" key="WeekView" title="{i18n>calendarTabMyWeek}" />
<SinglePlanningCalendarMonthView id="monthView" key="MonthView" title="{i18n>calendarTabMyMonth}" />
</views>
<!-- ... -->
</SinglePlanningCalendar>
However, I get the Message in console:
2022-10-26 11:15:16.235500 There is no such view. - Element sap.m.SinglePlanningCalendar#__component0---Calendar--planningCalendar
And the view is not selected.
During the debugging of SinglePlanningCalendar.js in SinglePlanningCalendar.prototype.setSelectedView, I noticed that the SinglePlanningCalendarView instances do not yet exist during the creation of the XML view .
Callstack:
SinglePlanningCalendar.setSelectedView (SinglePlanningCalendar.js:878)
ManagedObject.applySettings (ManagedObject.js?eval:1207)
(anonym) (ManagedObject.js?eval:520)
constructor (ManagedObject.js?eval:535)
constructor (Element.js?eval:200)
constructor (Control.js:181)
fnClass (Metadata.js?eval:454)
(anonym) (XMLTemplateProcessor.js:1644)
So in console sap.ui.getCore().byId("__component0---Calendar--planningCalendar").getViews() at that time returns an empty array and the method runs into an error.
After the complete rendering of the page, sap.ui.getCore().byId("__component0---Calendar--planningCalendar").getViews() returns the array of the SinglePlanningCalendarViews instances.
I know I can set the selected view in controller. However, I was wondering if there is a way to do it in the XML view.

Related

How to set visible property as false if model does not yet defined? (SAPUI5)

my model "categories" is defined on the second view controller and set as a global model. but in the first view, I have a button and set its visible condition like below
<Button text="Click Me" visible="{=${categories>/}.length > 0}" />
the button should only be visible when the categories model has data.
but since I have not yet navigated to the second view and my model is not yet defined. the expression binding is not working for the button in the first view. how do set the button visible as false if the model is not defined and has no data? only using XML, not with javascript.
/}.length > 0}" />
According the Expression Binding Documentation, you can use Function call and Binary logical operator.
With that, you can for example do this expression binding:
{= Array.isArray(${model}) && ${model}.length > 0 }
Check model exists and is an Array
And
Check model size > 0
With that if model is not existent or is not an array or is an empty array the answer is false otherwise true.
With you code it would give :
<Button text="Click Me" visible="{= Array.isArray(${categories>/}) && ${categories>/}.length > 0 }" />
& character from binary operator must be escaped in XML with &
XML syntax escaping rules

How to synchronize control values within different views

I would like to know how to get the content of TextArea, assign the value to a variable, set it to a model, and then set the variable to another TextArea in another view. I have coded some examples and it works, but not on TextArea.
Here is the example code:
// In init of the Component.js
this.setModel(new JSONModel(), "TransportModel"); // JSONModel required from "sap/ui/model/json/JSONModel"
// In *.controller.js
this.getView().getModel("TransportModel").setProperty("/", {
"Serial": this.byId("mat_serial").getValue() // "mat_serial" == id of the Input box in XML view
});
In the last step, I set the Text from a different View (also XML and Input Box) with the Value of the Model Element.
<Text text="{TransportModel>/Serial}" />
That worked pretty well.
But how to do the same with the TextArea? How can I do it based on this model? The value that I want to use from the first TextArea should also be on a TextArea in another view.
UI5 supports two-way data binding. I.e. if the user changes something in the UI (e.g. user types something in the text area), that change will be reflected automatically in other bindings that listen to the change.
<!-- In view 1 -->
<TextArea value="{TransportModel>/Serial}" />
<!-- In view 2 -->
<Text text="{TransportModel>/Serial}" />
No need to get input values by hand. Simply let the framework synchronize the value.
How to use a local json model:
Create
initItemViewModel: function () {
return new JSONModel({
Serial: ""
});
}
this._oViewModel = this.initItemViewModel();
this.setModel(this._oViewModel, "TransportModel");
Using
this.getView().getModel("TransportModel").setProperty("/Serial", serial);
<Text text="{TransportModel>/Serial}" width="auto" maxLines="1"/>

Slider used in Xamarin.froms to control value

I'm adding a slider into my xamarin app, but im using view models to capture values. How can I move the slider on the GUI and show the value incrementing up and down and then capture its value?
or is there a way I can include the "MySlider_ValueChanged" event and apply it to the view model page rather than the content page code behind file?
is there a way I can include the "MySlider_ValueChanged" event and apply it to the view model page rather than the content page code behind file?
You have to find a BindableProperty which could be bound inside view model(ICommand) ,it should do the same work as the event ValueChanged .
For exmaple
We could handle Tapped event of TapGestureRecognizer in page code behind , we also could create new ICommand inside view model , and bind it with Command of TapGestureRecognizer .
However, Slider does not have command whose function is detecting the value changed , there is only DragStartedCommand and DragCompletedCommand ,
so the only solution is to trigger your method inside the setter method of Value .
Xaml
<Slider Value="{Binding CurrentProgress}" />
View Model
public double CurrentProgress
{
get { return currentProgress; }
set
{
currentProgress = value;
NotifyPropertyChanged("CurrentProgress");
YourMethod(value);
}
}
Refer https://stackoverflow.com/a/25141043/8187800.

Setting multiple properties of a component with one function

I have a component in a list in a sapui5 XML view and I want to set multiple properties of that component with one function. E.g. I want to set text, status, tooltip and icon of an ObjectStatus together, because the values of those are all different facets of the same data. The issue is that i have to calculate the values to set to those properties from the model with the same relatively time-heavy function. If I write a separate formatter for each of those properties, it has to run the same function for each property. Instead of this I would like to write one function that runs this time-heavy function once and sets a value to all those properties at the same time.
To accomplish this, I have tried creating a sapui5 fragment that could be placed in the list and filled with different information by the createContent function for each instance of that fragment. However I cannot figure out how to do this.
In the view definitions I'm trying to instantiate the fragment like this:
<core:Fragment fragmentName="QuantificationParameter" type="JS" path="{project>}"/>
And then I'm trying to set different content to each instance of the fragment:
sap.ui.jsfragment("namespace.fragments.QuantificationParameter", {
createContent: function(oParentController) {
//Get the object bound to this list item
var derived; //Calculate some intermediate information from this object
return new sap.m.ObjectStatus({
icon: derived.icon,
text: derived.text,
state: derived.state,
tooltip: derived.tooltip
});
}
});
While debugging it seems that the createContent function of the fragment is run only once and I cannot figure out any way to access the data that I'm trying to bind to the fragment. Is there any way I can render different content to each instance of the fragment?
What you are searching for is called databinding.
But first of all: we do not use JS Fragments, due to the same reason we do not use JS views. Here s a little Blog written on that topic.
https://blogs.sap.com/2018/05/01/why-do-we-use-xml-views-rather-js-views-in-sapui5/
Now the databinding part:
I asume, that Fragment will have the same controlls for each instance and you just want the values to change. To do just that you need to create a JSONModel either in your BaseController or component.js. In this Model you store i.e. your Labels text.
Inside your Fragmet you bind that property to the label. Since JSONModels bindingmode is two way by default the Label will change dynamically if you update the model. You can update the model i.e. everytime the user clicks on one of your list items.
Framgmet example:
<core:FragmentDefinition
xmlns="sap.m"
xmlns:f="sap.ui.layout.form"
xmlns:core="sap.ui.core">
<f:SimpleForm
editable="true">
<f:content>
<Input
value="{baseModel>/inputA}"
type="Text"
placeholder="{i18n>placeHolder}"/>
<TextArea
value="{baseModel>/textA}"/>
<TextArea
editable="false"
value="{baseModel>/textB}"/>
</f:content>
</f:SimpleForm>
</core:FragmentDefinition>
creation of the model i.e in component.js:
var oBaseModel = new JSONModel({
inputA: "",
textA: "",
textB: ""
});
this.setModel(oBaseModel, "baseModel");
example for your press lit item funtion:
(should be in the controller of the view your list is located in)
onListPress: function (oEvent) {
var oLine = oEvent.getSource().getBindingContext("yourRemoteService").getObject();
this._oBaseModel.setProperty("/inputA", oLine.ListPropertyA);
this._oBaseModel.setProperty("/textA", oLine.ListPropertyb);
this._oBaseModel.setProperty("/textB", oLine.ListPropertyC);
}
You should really give that tutorial a go:
https://sapui5.hana.ondemand.com/#/topic/e5310932a71f42daa41f3a6143efca9c

How to get element's id of another view SAPUI5

I have 3 views say first,second & third. I need to access a vertical layout's id of second view from first view. For which I have used sap.ui.getCore().byId("__xmlview1--spend_layt"); to retrieve it. It works but when I navigate to third view & come back, id changes to __xmlview28--spend_layt & the control not works. How to fix this?
EDIT :
First.view.xml
<mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" controllerName="budgetspend.controller.First" xmlns:html="http://www.w3.org/1999/xhtml"
displayBlock="true">
<App id="BA_APP">
<pages>
<HBox width="100%" height="100%" id="header_container">
<items>
<Image class="logo" src="../images/logo_new.png"/>
<Image class="header" src="../images/header-bg.png"/>
<html:ul class="tab">
<html:li>
<html:a id="onBud" class="tablinks active">Tab 1
</html:li>
<html:li>
<html:a id="onSpend" class="tablinks">Tab 2</html:a>
</html:li>
</html:ul>
<mvc:XMLView viewName="budgetspend.view.second"/>
</items>
</HBox>
</pages>
</App>
</mvc:View>
In the second view, I use 2 vertical layouts. one for tab 1 & another for tab 2. Only one visible at a time. Tab click events are written in First.controller.js. I don't know how to access ID's of vertical layouts(in second view) from First.
I am just exploring how standard html will work on SAPUI5 as I am aware of using sap.m.IconTab.
What you are facing is due to the dynamic creation of elements. Every time you leave a screen and goes back into it, the items are regenerated, but they can't have the same ID, since they were used before.
One solution to this is to create a Utils folder, and create an object, let's say UIHelper.
This file would look like this:
jQuery.sap.declare('my.app.Utils.UIHelper');
my.app.Utils.UIHelper = {
controllerInstance1 : null,
controllerInstance2 : null,
controllerInstance3 : null,
//Add "getters and setters" for each of these attributes (repeat for Controller 2 & 3)
setControllerInstance1 : function(oController){
this.controllerInstance1 = oController;
},
getControllerInstance1 : function(){
return this.controllerInstance1;
}
};
Now, at the controller file for each of your views, you add the following line at the top of the file:
jQuery.sap.require('my.app.Utils.UIHelper');
And on the onInit event of those controllers, you set the controller instance on the UIHelper object:
my.app.Utils.UIHelper.setControllerInstance1(this);
And when you want to get the different views from anywhere in the code, assuming that the views are assigned to one of the controllers, you can just use the following:
my.app.Utils.UIHelper.getControllerInstance1().getView();
Update in my answer after the update on the question:
To access the layout from the second view, you could do the following:
var layout = my.app.Utils.UIHelper.getControllerInstanceView2().byId('spend_layt');