Child pages
  • Foundset property type

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagejs
titleBrowser side provided property content in model
myFoundset: {
    foundsetId: 2, // an identifier that allows you to use this foundset via the 'foundsetRef' type;
                   // when a 'foundsetRef' type sends a foundset from server to client (for example
                   // as a return value of callServerSideApi) it will translate to this identifier
                   // on client (so you can use it to find the actual foundset property in the model if
                   // server side script put it in the model as well); internally when sending a
                   // 'foundset' typed property to server through a 'foundsetRef' typed argument or prop,
                   // it will use this foundsetId as well to find it on server and give a real Foundset

    serverSize: 44, // the size of the foundset on server (so not necessarily the total record count
                    // in case of large DB tables)
    viewPort: {
        // this is the data you need to have loaded on client (just request what you need via provided
        // loadRecordsAsync or loadExtraRecordsAsync)
        startIndex: 15,
        size: 5,
        rows: [ { _svyRowId: 'someRowIdHASH1', name: "Bubu", type: 2 },
                { _svyRowId: 'someRowIdHASH2', name: "Ranger", type: 1 },
                { _svyRowId: 'someRowIdHASH3', name: "Yogy", type: 2 },
                { _svyRowId: 'someRowIdHASH4', name: "Birdy", type: 3 },
                { _svyRowId: 'someRowIdHASH5', name: "Wolfy", type: 4 } ]
    },
    selectedRowIndexes: [16], // array of selected records in foundset; indexes can be out of current
                              // viewPort as well
	sortColumns: 'orderid asc', // sort string of the foundset, the same as the one used in scripting for 
								// foundset.sort and foundset.getCurrentSort
    multiSelect: false, // the multiselect mode of the server's foundset; if this is false,
                        // selectedRowIndexes can only have one item in it
    hasMoreRows: false, // if the foundset is large and on server-side only part of it is loaded (so
                        // there are records in the foundset beyond 'serverSize') this is set to true;
                        // in this way you know you can load records even after 'serverSize' (requesting
                        // viewport to load records at index serverSize-1 or greater will load more
                        // records in the foundset)
    columnFormats: { name: (...), type: (...) }, // columnFormats is only present if you specify
                        // "provideColumnFormats": true inside the .spec file for this foundset property;
                        // it gives the default column formatting that Servoy would normally use for
                        // each column of the viewport - which you can then also use in the
                        // browser yourself

    /**
     * Request a change of viewport bounds from the server; the requested data will be loaded
     * asynchronously in 'viewPort'
     *
     * @param startIndex the index that you request the first record in "viewPort.rows" to have in
     *                   the real foundset (so the beginning of the viewPort).
     * @param size the number of records to load in viewPort.
     *
     * @return a $q promise that will get resolved when the requested records arrived browser-
     *                   side. As with any promise you can register success, error callbacks, finally, ...
     *                   See JSDoc of RequestInfoPromise.requestInfo and ChangeEvent.requestInfos
     *                   for more information about determining if a listener event was caused by this call.
     */
    loadRecordsAsync(startIndex: number, size: number): RequestInfoPromise<any>;

    /**
     * Request more records for your viewPort; if the argument is positive more records will be
     * loaded at the end of the 'viewPort', when negative more records will be loaded at the beginning
     * of the 'viewPort' - asynchronously.
     *
     * @param negativeOrPositiveCount the number of records to extend the viewPort.rows with before or
     *                                after the currently loaded records.
     * @param dontNotifyYet if you set this to true, then the load request will not be sent to server
     *                      right away. So you can queue multiple loadLess/loadExtra before sending them
     *                      to server. If false/undefined it will send this (and any previously queued
     *                      request) to server. See also notifyChanged().
     *
     * @return a $q promise that will get resolved when the requested records arrived browser-
     *                   side. As with any promise you can register success, error callbacks, finally, ...
     *                   That allows custom component to make sure that loadExtra/loadLess calls from
     *                   client do not stack on not yet updated viewports to result in wrong bounds.
     *                   See JSDoc of RequestInfoPromise.requestInfo and ChangeEvent.requestInfos
     *                   for more information about determining if a listener event was caused by this call.
     */
    loadExtraRecordsAsync(negativeOrPositiveCount: number, dontNotifyYet: boolean): RequestInfoPromise<any>;
 
    /**
     * Request a shrink of the viewport; if the argument is positive the beginning of the viewport will
     * shrink, when it is negative then the end of the viewport will shrink - asynchronously.
     *
     * @param negativeOrPositiveCount the number of records to shrink the viewPort.rows by before or
     *                                after the currently loaded records.
     * @param dontNotifyYet if you set this to true, then the load request will not be sent to server
     *                      right away. So you can queue multiple loadLess/loadExtra before sending them
     *                      to server. If false/undefined it will send this (and any previously queued
     *                      request) to server. See also notifyChanged().
     *
     * @return a $q promise that will get resolved when the requested records arrived browser
     *                   -side. As with any promise you can register success, error callbacks, finally, ...
     *                   That allows custom component to make sure that loadExtra/loadLess calls from
     *                   client do not stack on not yet updated viewports to result in wrong bounds.
     *                   See JSDoc of RequestInfoPromise.requestInfo and ChangeEvent.requestInfos
     *                   for more information about determining if a listener event was caused by this call.
     */
    loadLessRecordsAsync(negativeOrPositiveCount: number, dontNotifyYet: boolean): RequestInfoPromise<any>;

    /**
     * If you queue multiple loadExtraRecordsAsync and loadLessRecordsAsync by using dontNotifyYet = true
     * then you can - in the end - send all these requests to server (if any are queued) by calling
     * this method. If no requests are queued, calling this method will have no effect. It returns nothing.
     */
    notifyChanged: function(),

    /**
     * Sort the foundset by the dataproviders/columns identified by sortColumns.
     *
     * The name property of each sortColumn can be filled with the dataprovider name the foundset provides
     * or specifies. If the foundset is used with a component type (like in table-view) then the name is
     * the name of the component on who's first dataprovider property the sort should happen. If the
     * foundset is used with another foundset-linked property type (dataprovider/tagstring linked to 
     * foundsets) then the name you should give in the sortColumn is that property's 'idForFoundset' value
     * (for example a record 'dataprovider' property linked to the foundset will be an array of values
     * representing the viewport, but it will also have a 'idForFoundset' prop. that can be used for 
     * sorting in this call; this 'idForFoundset' was added in version 8.0.3).
     *
     * @param {JSONArray} sortColumns an array of JSONObjects { name : dataprovider_id,
     *                    direction : sortDirection }, where the sortDirection can be "asc" or "desc".
     * @return (added in Servoy 8.2.1) a $q promise that will get resolved when the new sort
     *                   will arrive browser-side. As with any promise you can register success, error
     *                   and finally callbacks.
     *                   See JSDoc of RequestInfoPromise.requestInfo and ChangeEvent.requestInfos
     *                   for more information about determining if a listener event was caused by this call.
     */
    sort(sortColumns: Array<{ name: string, direction: ("asc" | "desc") }>): RequestInfoPromise<any>;
 
    /**
     * Request a selection change of the selected row indexes. Returns a promise that is resolved
     * when the client receives the updated selection from the server. If successful, the array
     * selectedRowIndexes will also be updated. If the server does not allow the selection change,
     * the reject function will get called with the 'old' selection as parameter. 
     *
     * If requestSelectionUpdate is called a second time, before the first call is resolved, the
     * first call will be rejected and the caller will receive the string 'canceled' as the value
     * for the parameter serverRows.
     * E.g.: foundset.requestSelectionUpdate([2,3,4]).then(function(serverRows){},function(serverRows){});
     *
     * @return a $q promise that will get resolved when the requested selection was updated server-
     *                   side. As with any promise you can register success, error callbacks, finally, ...
     *                   See JSDoc of RequestInfoPromise.requestInfo and ChangeEvent.requestInfos
     *                   for more information about determining if a listener event was caused by this call.
     */
    requestSelectionUpdate(selectedRowIdxs: number[]): RequestInfoPromise<any>;
 
    /**
     * Sets the preferred viewPort options hint on the server for this foundset, so that the next
     * (initial or new) load will automatically return that many rows, even without any of the loadXYZ
     * methods above being called.
     *
     * You can use this when the component size is not known initially and the number of records the
     * component wants to load depends on that. As soon as the component knows how many it wants 
     * initially it can call this method.
     *
     * These can also be specified initially using the .spec options "initialPreferredViewPortSize" and
     * "sendSelectionViewportInitially". But these can be altered at runtime via this method as well
     * because they are used/useful in other scenarios as well, not just initially: for example when a
     * related foundset changes parent record, when a search/find is performed and so on.
     *
     * @param preferredSize the preferred number or rows that the viewport should get automatically
     *                      from the server.
     * @param {boolean} sendViewportWithSelection if this is true, the auto-sent viewport will contain
     *                                            the selected row (if any).
     * @param {boolean} centerViewportOnSelected if this is true, the selected row will be in the middle
     *                                           of auto-sent viewport if possible. If it is false, then
     *                                           the foundset property type will assume a 'paging'
     *                                           strategy and will send the page that contains the 
     *                                           selected row (here the page size is assumed to be
     *                                           preferredSize).
     */
    setPreferredViewportSize: function(preferredSize, sendViewportWithSelection, centerViewportOnSelected),
		
    /**
     * It will send a data update for a cell (ros & column) in the foundset to the server.
     * Please make sure to adjust the viewport value as well not just call this method.
     *
     * This method is useful if you do not want to add angular watches on data (so calculated
     * pushToServer for the foundset property is set to just 'allow'). Then server will accept
 * Then server will accept* data changes from this property, but there are no automatic watches to detect the changes
so the component must call * so the component must *call this method instead - when it wants to change the data in a cell.
     *
      * @param rowID the _svyRowId (so $foundsetTypeConstants.ROW_ID_COL_KEY) column of the client side row
     * @param columnID the name of the column to be updated on server (in that row).
     * @param newValue the new data in that cell
     * @param oldValue the old data that used to be in that cell
    	 */
    updateViewportRecord(rowID: string, columnID: string, newValue: any, oldValue: any): void;

    /**
     * Add a change listener that is interested in knowing of any incoming changes (from server)
     * for this foundset property. See the "Adding a change listener" section below for more information.
     */
    addChangeListener : function(listener),

    /**
     * Removes the given change listener from this foundset property.
     */
    removeChangeListener: function(listener),
 
    /**
     * Receives a client side rowID (taken from myFoundsetProp.viewPort.rows[idx]
     * [$foundsetTypeConstants.ROW_ID_COL_KEY]) and gives a Record reference, an object
     * which can be resolved server side to the exact Record via the 'record' property type;
     * for example if you call a handler or a $scope.svyServoyapi.callServerSideApi(...) and want
     * to give it a Record as parameter and you have the rowID and foundset in your code,
     * you can use this method. E.g: $scope.svyServoyapi.callServerSideApi("doSomethingWithRecord",
     *                     [$scope.model.myFoundsetProp.getRecordRefByRowID(clickedRowId)]);
     *
     * NOTE: if in your component you know the whole row (so myFoundsetProp.viewPort.rows[idx])
     * already - not just the rowID - that you want to send you can just give that directly to the
     * handler/serverSideApi; you do not need to use this method in that case. E.g:
     * // if you have the index inside the viewport
     * $scope.svyServoyapi.callServerSideApi("doSomethingWithRecord",
     *           [$scope.model.myFoundsetProp.viewPort.rows[clickedRowIdx]]);
     * // or if you have the row directly
     * $scope.svyServoyapi.callServerSideApi("doSomethingWithRecord", [clickedRow]);
     *
     * This method has been added in Servoy 8.3.
     */
	getRecordRefByRowID: function(rowId)

}

// where the return value for some of the client side foundset methods is:

/**
 * Besides working like a normal IPromise that you can use to get notified when some action is done
 * (success/error/finally), chain etc., this promise also  * contains field "requestInfo" which can be set
 * by the user and could later be reported in some listener events back to the user (in case this same
action * *action is going to trigger those listeners as well).
 *
 * @since 2021.09
 */
interface RequestInfoPromise<T> extends angular.IPromise<T> {


       /**
     * You can assign any value to it. The value that you assign - if any - will be given back in the
     * event object of any listener that will be triggered
     * as a result of the promise's action. So in
     * case the same action, when done, will trigger both the "then" of the Promise and a separate
listener,     * *listener, that separate listener will contain this "requestInfo" value.
     *
     * This is useful for some components that want to know if some change (reported by the listener)
     * happened due to an action that the component
     * requested or due to changes in the outside world.
     * (eg: FoundsetPropertyValue.loadRecordsAsync(...) returns RequestInfoPromise and 
     * ChangeEvent.requestInfos array can return that RequestInfoPromise.requestInfo on the event that
     * was triggered by that loadRecordsAsync)
     */
    requestInfo?: any;

}

...

Code Block
languagejs
titlewhat "changes" parameter can contain:
// ChangeEvent
{

    // If this change event is caused by one or more calls (by the component) on the IFoundset obj
    // (like loadRecordsAsync requestSelectionUpdate and so on),
    // and the caller then assigned a value to
    // the returned RequestInfoPromise's "requestInfo" field, then that value will be present in this array.
    //
    // This is useful for some components that want to know if some change (reported in this ChangeEvent)
    // happened due to an action that the component
    // requested or due to changes in the outside world. (eg:
    // IFoundset.loadRecordsAsync(...) returns RequestInfoPromise and ChangeEvent.requestInfos array can
 // ChangeEvent.requestInfos array can// contain that RequestInfoPromise.requestInfo on the event that was triggered by that loadRecordsAsync)
    //
    // @since 2021.09
    $foundsetTypeConstants.NOTIFY_REQUEST_INFOS: any[],

    // If a a full value update was received from server, this key is set; if newValue is non-null:
    //   - prior to Servoy version 2021.06: newValue is a new reference, but it will automatically get
    //     the old value's listeners registered to itself
    //   - starting with Servoy 2021.06: the old value's reference will be reused (so the reference of
    //     the foundset property doesn't change, just it's contents are updated) and oldValue given
    //     below is actually a shallow-copy of the old value's properties/keys; this can help
    //     in some component implementations
    $foundsetTypeConstants.NOTIFY_FULL_VALUE_CHANGED: { oldValue : ..., newValue : ... },

    // the following keys appear if each of these got updated from server; the names of those
    // constants suggest what it was that changed; oldValue and newValue are the values for what changed
    // (e.g. new server size and old server size) so not the whole foundset property new/old value
    $foundsetTypeConstants.NOTIFY_SERVER_SIZE_CHANGED: { oldValue : ..., newValue : ... },
    $foundsetTypeConstants.NOTIFY_HAS_MORE_ROWS_CHANGED:  { oldValue : ..., newValue : ... },
    $foundsetTypeConstants.NOTIFY_MULTI_SELECT_CHANGED:  { oldValue : ..., newValue : ... },
    $foundsetTypeConstants.NOTIFY_COLUMN_FORMATS_CHANGED:  { oldValue : ..., newValue : ... },
    $foundsetTypeConstants.NOTIFY_SORT_COLUMNS_CHANGED:  { oldValue : ..., newValue : ... },
    $foundsetTypeConstants.NOTIFY_SELECTED_ROW_INDEXES_CHANGED:  { oldValue : ..., newValue : ... },
    $foundsetTypeConstants.NOTIFY_VIEW_PORT_START_INDEX_CHANGED:  { oldValue : ..., newValue : ... },
    $foundsetTypeConstants.NOTIFY_VIEW_PORT_SIZE_CHANGED:  { oldValue : ..., newValue : ... },
    $foundsetTypeConstants.NOTIFY_VIEW_PORT_ROWS_COMPLETELY_CHANGED:  { oldValue : ..., newValue : ... },

    // if we received add/remove/change operations on a set of rows from the viewport, this key
    // will be set; as seen below, it contains "updates" which is an array that holds a sequence of
    // granular update operations to the viewport; the array will hold one or more granular add, remove
    // or update operations;
    //
    // BEFORE Servoy 8.4: all the "startIndex" and "endIndex" values below are relative to the viewport's
    // state after all previous updates in the array were already processed (so they are NOT relative to
    // the initial or final state of the viewport data!). Updates can come in a random order so there is
    // NO guarantee related to each change/insert/delete indexes pointing to the correct new data in the
    // final current viewport state
    //
    // STARTING WITH Servoy 8.4: all the "startIndex" and "endIndex" values below are relative to the
    // viewport's state after all previous updates in the array were already processed. But due to some
    // pre-processing that happens server-side (it merges and sorts these ops), the indexes of update
    // operations THAT POINT TO DATA (so ROWS_INSERTED and ROWS_CHANGED operations) are relative also to
    // the viewport's final/current state, so after ALL updates in the array were already processed
    // (so these indexes are correct both related to the intermediate state of the viewport data 
    // and to the final state of viewport data).
    // This means that it is now easier to apply UI changes to the component as these granular updates
    // GUARANTEE that if you apply them in sequence (one by one) to the component's UI (delete, insert and
    // change included) you can safely use the indexes in there to get new data from the present state
    // of the viewport.
    //
    // indexes are 0 based
    $foundsetTypeConstants.NOTIFY_VIEW_PORT_ROW_UPDATES_RECEIVED: {

        // DEPRECATED in Servoy 8.4: granular updates are much easier to apply now; see comment above
        // Added in 8.3.2; sometimes knowing the old
        // viewport size helps calculate incomming granular updates easier
        $foundsetTypeConstants.NOTIFY_VIEW_PORT_ROW_UPDATES_OLD_VIEWPORTSIZE: ...,

        // starting with 8.3.2 you can use instead of 'updates' below the new constant;
        // $foundsetTypeConstants.NOTIFY_VIEW_PORT_ROW_UPDATES
        // before 8.3.2 just use 'updates';
        updates : [
            {
                    type : $foundsetTypeConstants.ROWS_CHANGED,
                    startIndex : ...,
                    endIndex : ...
            },
            {
                    // NOTE: insert signifies an insert into the client viewport, not necessarily
                    // an insert in the foundset itself; for example calling "loadExtraRecordsAsync"
                    // can result in an insert notification + bigger viewport size notification,
                    // with removedFromVPEnd = 0
                    type : $foundsetTypeConstants.ROWS_INSERTED,
                    startIndex : ...,
                    endIndex : ...,

                    // DEPRECATED starting with Servoy 8.4; it would always be 0 here
                    // as server-side code will add a separate delete operation instead - if necessary
                    // BEFORE 8.4: when an INSERT happened but viewport size remained the same, it was
                    // possible for some of the rows that were previously at the end of the viewport
                    // to slide out of it; "removedFromVPEnd" gives the number of such rows that were
                    // removed from the end of the viewport due to this insert operation;
                    removedFromVPEnd : ...
            },
            {
                    // NOTE: delete signifies a delete from the client viewport, not necessarily
                    // a delete in the foundset itself; for example calling "loadLessRecordsAsync" can
                    // result in a delete notification + smaller viewport size notification,
                    // with appendedToVPEnd = 0                                 
                    type : $foundsetTypeConstants.ROWS_DELETED,
                    startIndex : ...,
                    endIndex : ...,

                    // DEPRECATED starting with Servoy 8.4; it would always be 0 here
                    // as server-side code will add a separate insert operation instead - if necessary
                    // BEFORE 8.4: when a DELETE happened inside the viewport but there were more rows
                    // available in the foundset after current viewport, it was possible for some of those
                    // rows to slide into the viewport; "appendedToVPEnd " gives the number of such rows
                    // that were appended to the end of the viewport due to this delete operation
                    appendedToVPEnd : ...
            }
        ]
    }

}

...