Search code examples
sapui5

How to bind a calendar and two time pickers properly to a sap.m.table?


I am learning SAPUI5 at the moment and created a little application for myself to play around and learn by practice. Before I get to my question, I will provide some short information about my app, so you know what I am trying to do and what should be the expected result.

What does the app?

The only thing this application does is providing a calendar and a table for the user. If the user clicks on a date, then the table should be filled with this date and two time pickers to give a start and end time for this selected day. For every date a new row should be created.

The actual problem:

The problem is a design problem I guess. The table gets filled with the dates and the time pickers, but my way of doing this is, is bad practice I guess. I store my selected dates in two models, one for the calendar, one copy to bind it to the table. That works and dates are saved and I can access the data via model. When a new dates get added to the table, the two timepickers get added too because they are provided in the ColumnListItem in the XML view, but no model is bound to them nor do I have access to the values of the timepickers e.g. via ID. And here is the problem, until now I found no proper way of how to them bind to a model or another clean way nor to access the values of the created timepickers.

The question:

How would you implement this in a clean way, so that the time pickers are bound in a right way maybe to a model or models? and you can access their data? I would be thankful if you could give me an advice or hint how I should implement this in a clean way since I want to learn from this and don't want to start hacking around with bad practices just to achieve the goal in shorter time.

The relevant sourcecode:

Controller:

var CalendarController = Controller.extend("sap.ui.unified.sample.CalendarMultipleDaySelection.CalendarMultipleDaySelection", {
        oFormatYyyymmdd: null,
        oModel: null,
        onInit: function(oEvt) {
            this.oFormatYyyymmdd = sap.ui.core.format.DateFormat.getInstance({
                pattern: "dd.MM.yyyy",
                calendarType: sap.ui.core.CalendarType.Gregorian
            });
            this.oModel = new JSONModel({
                selectedDates: []
            });
            this.oCopyModel = new JSONModel({
                selectedDates: []
            });
            var oCalendar = this.getView().byId("calendar");
            oCalendar.setModel(this.oModel);
        },
        handleCalendarSelect: function(oEvt) {
            var oCalendar = oEvt.oSource;
            var aSelectedDates = oCalendar.getSelectedDates();
            console.log(aSelectedDates);
            var oDate;
            var oData = {
                selectedDates: []
            };
            var oTable = this.getView().byId("dateTable");


            if (aSelectedDates.length > 0) {
                for (var i = 0; i < aSelectedDates.length; i++) {
                    oDate = aSelectedDates[i].getStartDate();
                    oData.selectedDates.push({
                        Date: this.oFormatYyyymmdd.format(oDate)
                    });
                }
                this.oModel.setData(oData);
                if (this.oCopyModel.getProperty("/selectedDates/length") >= 0) {
                    this.oCopyModel.setData(oData);
                    oTable.setModel(this.oCopyModel);
                }
            } else {
                this._clearModel();
            }
        },
        return CalendarController;

View:

<content>
<unified:Calendar id="calendar" select="handleCalendarSelect" intervalSelection="false" singleSelection="false"/>
<Table id="dateTable" items="{path: '/selectedDates', sorter: {path: 'Date', comparator: '.dateComperator'}}"mode="None" fixedLayout="true">
    <columns>
        <Column>
            <header>
                <Text text="Date"/>
            </header>

        </Column>
        <Column>
            <header>
                <Text text="Beginning"/>
            </header>
        </Column>
        <Column>
            <header>
                <Text text="End"/>
            </header>
        </Column>
    </columns>
    <ColumnListItem>
        <Text text="{Date}"/>
        <TimePicker value="10:00" valueFormat="HH:mm" displayFormat="HH:mm" change="handleChange"/>
        <TimePicker value="11:00" valueFormat="HH:mm" displayFormat="HH:mm" change="handleChange"/>
    </ColumnListItem>
</Table>

Kind regards

Maximilian


Solution

  • I created a small example:

    https://next.plnkr.co/edit/OGmJimjF2YZ46mv6DsF2?preview

    A few points:

    • I simply added a few properties (startTime and endTime) to a selected date. You can now modify the time with the timepicker, the changes are stored in the model.
    • The data binding of the calender seems broken. I also had to use getSelectedDates. This may be due to singleSelection="false". When using single selection you can access the selected date (or interval) via data binding.
    • Never access internal properties (oEvt.oSource). There are accessors for this (oEvt.getSource()).