Child pages
  • Foundset property type

Versions Compared

Key

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

...

  • a (parent) form's foundset
  • a related foundset
  • a separate foundset (of any table; smilar to JSDatabaseManager.getFoundset()). When this option is chosen the user can also choose whether or not the separate foundset should load all records initially. (if not checked, contents can be loaded at any time from scripting)
  • "- none -" which means that you are going to set that foundset at runtime through scripting.

Foundset property value in browser

...

Code Block
languagejs
titleBrowser side provided property content in model
myFoundset: {
    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
    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.
     */
     loadRecordsAsync: function(startIndex, size),

    /**
     * Request more records for your viewPort; if the argument is positive more records will be* @return {promise} a $q promise that will get resolved when the requested records arrived browser-side.
     *              * loaded at the end ofAs the 'viewPort', when negative more records will be loaded at the beginningwith any promise you can register success and error callbacks, finally, ...
     */
 * of the 'viewPort' - asynchronously.loadRecordsAsync: function(startIndex, size),

    /**
     * @paramRequest negativeOrPositiveCountmore therecords numberfor ofyour records to extendviewPort; if the viewPort.rowsargument withis beforepositive ormore records will be
  *   * loaded at the end of the 'viewPort', when negative more records will be loaded at the beginning
     * of the 'viewPort' - asynchronously.
 after the current loaded records.*
     */ @param negativeOrPositiveCount the number loadExtraRecordsAsync: function(negativeOrPositiveCount),
 
    /**of records to extend the viewPort.rows with before or
     * Sort the foundset by the dataproviders/columns identified by sortColumns.      *      * The name property of each sortColumn can be filled with after the dataprovidercurrently nameloaded therecords.
foundset provides    * @param *dontNotifyYet orif specifies.you Ifset thethis foundsetto istrue, usedthen withthe aload componentrequest typewill (likenot in table-view) then the name is thebe sent to server right away.
     * name of the component on who's first dataprovider property the sort should happen. If the foundset      *so isyou usedcan withqueue another foundset-linked property type (dataprovider/tagstring linked to foundsets) thenmultiple loadLess/loadExtra before sending them to server.
     *
 * the name you should* give@return in{promise} thea sortColumn$q ispromise that property's 'idForFoundset' value (for example a will get resolved when the requested records arrived browser-side.
     * record 'dataprovider' property linked to the foundset will be an array of values representing the    As with * viewport, but it will also have a 'idForFoundset' prop. that can be used for sorting in this call;any promise you can register success and error callbacks, finally, ...
     *         * this 'idForFoundset' was added in version 8.0.3).   That allows custom *component to make sure that  * @param {JSONArray} sortColumns an array of JSONObjects { name : dataprovider_id,
     loadExtra/loadLess calls from client
     *                   do directionnot :stack sortDirectionon },not whereyet theupdated sortDirectionviewports canto beresult "asc"in orwrong "desc"bounds.
      */
    sortloadExtraRecordsAsync: function(sortColumnsnegativeOrPositiveCount, dontNotifyYet),
 
    /**
     * Request a selection changeshrink of the selectedviewport; rowif indexes.the Returnsargument ais promisepositive thatthe isbeginning resolvedof the viewport will
  * when the client receives  * shrink, when it is negative then the updatedend selectionof from the server.viewport Ifwill successful,shrink the- arrayasynchronously.
     *
selectedRowIndexes   will also be* updated.@param IfnegativeOrPositiveCount the servernumber of doesrecords notto allowshrink the selection change, viewPort.rows by before or
     * the reject function will get called with the 'old' selection as parameter.       *      * If requestSelectionUpdate is called a second time, beforeafter the firstcurrently callloaded isrecords.
resolved, the    * @param dontNotifyYet *if firstyou callset willthis beto rejectedtrue, andthen the callerload request will receivenot thebe stringsent 'canceled'to asserver theright valueaway.
     *        for the parameter serverRows.      * E.g.: foundset.requestSelectionUpdate([2,3,4]).then(function(serverRows){},function(serverRows){});   so you can */queue multiple loadLess/loadExtra before sending requestSelectionUpdatethem : function(selectedRowIdxs),to server.
      /**
     * Sets@return the{promise} preferreda viewport$q sizepromise onthat thewill serverget forresolved thiswhen foundset,the sorequested thatrecords the next (initial) loadarrived browser-side.
     *              * will give back that viewport.As Usewith thisany whenpromise theyou componentcan resizesregister itselfsuccess and doesn't know initially error callbacks, finally, ...
     * what it can show before hand.      */     setPreferredViewportSize: function(size) 
}

 

  • serverSize is controlled by the server; you should not change it

  • viewPort initially has size 0, and startIndex 0. When the component detects that records are available (serverSize > 0) it care request viewPort contents using one of the two load async methods
    • viewPort.startIndex and viewPort.size will have the values requested by the async load methods. But if for example you are using data at the end of the foundset and records are deleted from there then viewport.size will be corrected/decreased from server (as there aren't enough records). A similar thing can happen to viewPort.startIndex. Do not modify these directly as that will have no effect. Use the load async methods instead.
    • viewPort.rows contains the viewPort data. Each item of the array represents data from a server-side record. Each item will always contain a "_svyRowId" ($foundsetTypeConstants.ROW_ID_COL_KEY in angular world) entry that uniquely identifies the record on server. Then there's one entry for every dataprovider that the component needs to use (how those are selected is described below). You should never change the "_svyRowId" entry, but it is possible to change the values of any of the other entries - the new values will be pushed back into the server side record that they belong to (if pushToServer is set on the foundset property to allow/shallow or deep; see "Data synchronization" section of https://wiki.servoy.com/display/public/DOCS/Specification).
  • selectedRowIndexes is an array of selected foundset record indexes. This can get updated by the server if foundset selection changes server side. You can change the contents of this array to change foundset selection (new selection will be pushed to server). However, the preferred way of changing the record selection is by using "requestSelectionUpdate".
  • multiselect represents the foundset multiselect state; do not change it as it will not be pushed to server.
  • columnFormats represents the default column formats for the columns given in the viewport; do not change this - only server pushes this information to the client if asked to do so by the .spec file. It is only present if you specify "provideColumnFormats": true inside the .spec file for this foundset property.
  • hasMoreRows true if the server side foundset has loaded only a part/chunk of it's records (in case of very large foundsets). In that case there are records even after 'serverSize'.  It is controlled and updated by the server; you should not change it.

Defining/using a foundset property with a random set of dataproviders

A web component might want to work with as many dataproviders available in the viewport as the developer wants. Servoy Developer will allow selecting any number of dataproviders of the foundset to be sent to browser web component property value (through the properties view for the foundset typed property; use sub-property 'dataproviders').

 

For example a component that shows graphical representation of data might allow adding as many 'categories' to it as the developer wants to (each category getting data from one viewport column/dataprovider) .

.spec file

Code Block
languagejs
"myFoundset": { "type": "foundset", "dynamicDataproviders": true }

So the component has a property called "myfoundset" that it wants linked to any foundset chosen in ServoyDeveloper, and it allows the developer to choose in properties view any number of dataproviders from the foundset.

browser js

Let's say the developer has chosen a foundset and 3 dataproviders (for example 3 database columns) from it. Those would generate for example a viewPort like this inside the browser property.

Code Block
languagejs
titleBrowser side provided property content in model
myFoundset: {
    (...)
    viewPort: {
        startIndex: 15,
        size: 2,
        rows: [ { _svyRowId: 'someRowIdHASH1', dp1: (...), dp2: (...), dp3: (...) },
                { _svyRowId: 'someRowIdHASH2', dp1: (...), dp2: (...), dp3: (...) } ],
        (...)
    },
    (...)
}

Notice the fixed column names: dp1, dp2, ... dp[N] where N is the number of foundset dataproviders that the developer has chosen.

Defining/using a foundset property with a fixed set of dataproviders

 

A web component can specify in it's .spec file that it requires a foundset property and a fixed number of dataproviders from it. The foundset and required dataproviders are then selected by the developer when creating a solution (using the properties view, 'dataproviders' sub-property).

.spec file

Code Block
languagejs
"myFoundset": { "type": "foundset", "dataproviders": ["firstName", "lastName"] }

So the component has a property called "myfoundset" that it wants linked to any foundset chosen in ServoyDeveloper, and it needs two dataproviders from that foundset to be present in the foundset's property viewport.

browser js

Let's say the developer has chosen a foundset and selected for "firstName" a foundset dataprovider (for example a database column called parentFirstName) and for lastName another dataprovider (for example a database column called parentLastName). Those would generate for example a viewport like this inside the browser property:

Code Block
languagejs
titleBrowser side provided property content in model
myFoundset: {
    (...)
    viewPort: {
        startIndex: 15,
        size: 2,
        rows: [ { _svyRowId: 'someRowIdHASH1', firstName: (...), lastName: (...) },
                { _svyRowId: 'someRowIdHASH2', firstName: (...), lastName: (...) } ],
        (...)
    },
    (...)
}

In this way any foundset dataprovider/column can be mapped to one of the two dataproviders that the component requires. The actual foundset dataprovider name is not even used in browser js.

Defining/using a foundset property that provides default formatting information for columns

 

A web component can specify in it's .spec file that it requires the foundset property to provide default formatting information for it's columns. We will use a foundset property with fixed number of dataproviders as an example, but it will work the same for other ways of specifying the dataproviders.

.spec file

Code Block
languagejs
"myFoundset": { "type": "foundset", "dataproviders": ["image", "age"], "provideColumnFormats": true }

So the component has a property called "myfoundset" that it wants linked to any foundset chosen in ServoyDeveloper, and it needs two dataproviders from that foundset to be present in the foundset's property viewport. For each of the two columns it will also receive default formatting information.

browser js

Let's say the developer has chosen a foundset and selected for "image" a foundset dataprovider (for example a database column called 'photo') and for age another dataprovider (for example a database column called 'estimatedStructureAge'). Those would generate a viewport and formatting information similar to the following inside the browser property (note that the column format actual contents might change as needed - this is what Servoy default components receive as well for their component properties):

Code Block
languagejs
titleBrowser side provided property content in model
myFoundset: {
    (...)
    viewPort: {
        startIndex: 15,
        size: 2,
        rows: [ { _svyRowId: 'someRowIdHASH1', image: (...), age: (...) },
                { _svyRowId: 'someRowIdHASH2', image: (...), age: (...) } ],
        (...)
    },
    columnFormats: {
        image: {
            placeHolder: null,
            maxLength: 2147483647,
            isNumberValidator: false,
            edit: null,
            isMask: false,
            display: null,
            type: "MEDIA",
            allowedCharacters: null
        },

        age: {
            placeHolder: null,
            percent: "%",
            isNumberValidator: false,
            edit: null,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.
     */
    loadLessRecordsAsync: function(negativeOrPositiveCount, dontNotifyYet),
 
    /**
     * 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".
     */
    sort: function(sortColumns),
 
    /**
     * 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){});
     */
    requestSelectionUpdate : function(selectedRowIdxs),
 
    /**
     * 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)

}

 

  • serverSize is controlled by the server; you should not change it

  • viewPort initially has size 0, and startIndex 0. When the component detects that records are available (serverSize > 0) it care request viewPort contents using one of the two load async methods
    • viewPort.startIndex and viewPort.size will have the values requested by the async load methods. But if for example you are using data at the end of the foundset and records are deleted from there then viewport.size will be corrected/decreased from server (as there aren't enough records). A similar thing can happen to viewPort.startIndex. Do not modify these directly as that will have no effect. Use the load async methods instead.
    • viewPort.rows contains the viewPort data. Each item of the array represents data from a server-side record. Each item will always contain a "_svyRowId" ($foundsetTypeConstants.ROW_ID_COL_KEY in angular world) entry that uniquely identifies the record on server. Then there's one entry for every dataprovider that the component needs to use (how those are selected is described below). You should never change the "_svyRowId" entry, but it is possible to change the values of any of the other entries - the new values will be pushed back into the server side record that they belong to (if pushToServer is set on the foundset property to allow/shallow or deep; see "Data synchronization" section of https://wiki.servoy.com/display/public/DOCS/Specification).
  • selectedRowIndexes is an array of selected foundset record indexes. This can get updated by the server if foundset selection changes server side. You can change the contents of this array to change foundset selection (new selection will be pushed to server). However, the preferred way of changing the record selection is by using "requestSelectionUpdate".
  • multiselect represents the foundset multiselect state; do not change it as it will not be pushed to server.
  • columnFormats represents the default column formats for the columns given in the viewport; do not change this - only server pushes this information to the client if asked to do so by the .spec file. It is only present if you specify "provideColumnFormats": true inside the .spec file for this foundset property.
  • hasMoreRows true if the server side foundset has loaded only a part/chunk of it's records (in case of very large foundsets). In that case there are records even after 'serverSize'.  It is controlled and updated by the server; you should not change it.

Defining/using a foundset property with a random set of dataproviders

A web component might want to work with as many dataproviders available in the viewport as the developer wants. Servoy Developer will allow selecting any number of dataproviders of the foundset to be sent to browser web component property value (through the properties view for the foundset typed property; use sub-property 'dataproviders').

 

For example a component that shows graphical representation of data might allow adding as many 'categories' to it as the developer wants to (each category getting data from one viewport column/dataprovider) .

.spec file

Code Block
languagejs
"myFoundset": { "type": "foundset", "dynamicDataproviders": true }

So the component has a property called "myfoundset" that it wants linked to any foundset chosen in ServoyDeveloper, and it allows the developer to choose in properties view any number of dataproviders from the foundset.

browser js

Let's say the developer has chosen a foundset and 3 dataproviders (for example 3 database columns) from it. Those would generate for example a viewPort like this inside the browser property.

Code Block
languagejs
titleBrowser side provided property content in model
myFoundset: {
    (...)
    viewPort: {
        startIndex: 15,
        size: 2,
        rows: [ { _svyRowId: 'someRowIdHASH1', dp1: (...), dp2: (...), dp3: (...) },
                { _svyRowId: 'someRowIdHASH2', dp1: (...), dp2: (...), dp3: (...) } ],
        (...)
    },
    (...)
}

Notice the fixed column names: dp1, dp2, ... dp[N] where N is the number of foundset dataproviders that the developer has chosen.

Defining/using a foundset property with a fixed set of dataproviders

 

A web component can specify in it's .spec file that it requires a foundset property and a fixed number of dataproviders from it. The foundset and required dataproviders are then selected by the developer when creating a solution (using the properties view, 'dataproviders' sub-property).

.spec file

Code Block
languagejs
"myFoundset": { "type": "foundset", "dataproviders": ["firstName", "lastName"] }

So the component has a property called "myfoundset" that it wants linked to any foundset chosen in ServoyDeveloper, and it needs two dataproviders from that foundset to be present in the foundset's property viewport.

browser js

Let's say the developer has chosen a foundset and selected for "firstName" a foundset dataprovider (for example a database column called parentFirstName) and for lastName another dataprovider (for example a database column called parentLastName). Those would generate for example a viewport like this inside the browser property:

Code Block
languagejs
titleBrowser side provided property content in model
myFoundset: {
    (...)
    viewPort: {
        startIndex: 15,
        size: 2,
        rows: [ { _svyRowId: 'someRowIdHASH1', firstName: (...), lastName: (...) },
                { _svyRowId: 'someRowIdHASH2', firstName: (...), lastName: (...) } ],
        (...)
    },
    (...)
}

In this way any foundset dataprovider/column can be mapped to one of the two dataproviders that the component requires. The actual foundset dataprovider name is not even used in browser js.

Defining/using a foundset property that provides default formatting information for columns

 

A web component can specify in it's .spec file that it requires the foundset property to provide default formatting information for it's columns. We will use a foundset property with fixed number of dataproviders as an example, but it will work the same for other ways of specifying the dataproviders.

.spec file

Code Block
languagejs
"myFoundset": { "type": "foundset", "dataproviders": ["image", "age"], "provideColumnFormats": true }

So the component has a property called "myfoundset" that it wants linked to any foundset chosen in ServoyDeveloper, and it needs two dataproviders from that foundset to be present in the foundset's property viewport. For each of the two columns it will also receive default formatting information.

browser js

Let's say the developer has chosen a foundset and selected for "image" a foundset dataprovider (for example a database column called 'photo') and for age another dataprovider (for example a database column called 'estimatedStructureAge'). Those would generate a viewport and formatting information similar to the following inside the browser property (note that the column format actual contents might change as needed - this is what Servoy default components receive as well for their component properties):

Code Block
languagejs
titleBrowser side provided property content in model
myFoundset: {
    (...)
    viewPort: {
        startIndex: 15,
        size: 2,
        rows: [ { _svyRowId: 'someRowIdHASH1', image: (...), age: (...) },
                { _svyRowId: 'someRowIdHASH2', image: (...), age: (...) } ],
        (...)
    },
    columnFormats: {
        image: {
            placeHolder: null,
            maxLength: 2147483647,
            isNumberValidator: false,
            edit: null,
            isMask: false,
            display: null,
            type: "MEDIA",
            allowedCharacters: null
        },

        age: {
            placeHolder: null,
            percent: "%",
            isNumberValidator: false,
            edit: null,
            isMask: false,
            display: "#,#00.###",
            type: "NUMBER",
            allowedCharacters: null
        }
    }
}

The formatting information is similar to what default Servoy components get for their format properties, so it could be used in a similar way (for example through $formatterUtils; for more details check out the source code - servoyformat.js, textfield.js).

Defining initial load options for a foundset property

A web component can specify in it's .spec file that initially, at first show or each time the foundset gets completely refreshed it wants to automatically receive a number of rows in the viewport. This is useful to avoid some round trips between client and server and send data directly. It is configurable because some component may want to send no records initially while others might need to send many. This is done via the initialPreferredViewPortSize option. Default value is 50.

There is another option sendSelectionViewportInitially which allows a component to say wether this set of initial rows should contain the selected row (if any) or start at first row. The selected row will be in the center of this initial viewPort if possible when this option is "true". This option is "false" by default.

Both of these options can be altered at runtime by browser-side scripting using "setPreferredViewportSize(...)"; see above.

.spec file

Code Block
languagejs
"myFoundset": { "type": "foundset", "dataproviders": ["image", "age"],
                     isMask: false,             display: "#,#00.###"initialPreferredViewPortSize": 130,
            type: "NUMBER",             allowedCharacters: null         }"sendSelectionViewportInitially": true    }
}

...

Linking other "foundset aware" property types to a foundset property

...

Examples of foundset aware types are 'component', 'dataprovider', 'tagstring'.

.spec file

One child component linked to the foundset:

...