📄 databoundcomponent.js
字号:
/*
* Isomorphic SmartClient
* Version 6.5 (2008-04-30)
* Copyright(c) 1998-2007 Isomorphic Software, Inc. All rights reserved.
* "SmartClient" is a trademark of Isomorphic Software, Inc.
*
* licensing@smartclient.com
*
* http://smartclient.com/license
*/
//> @interface DataBoundComponent// A DataBoundComponent is a widget that can configure itself for viewing or editing objects which// share a certain schema by "binding" to the schema for that object (called a "DataSource").// <P>// A schema (or DataSource) describes an object as consisting of a set of properties (or// "fields").// <P>// DataBoundComponents have a +link{dataBoundComponent.dataSource,common set of APIs} for// dealing with binding to DataSources, // +link{dataBoundComponent.fields,overriding or augmenting} the schema information// provided by a DataSource, and manipulating objects or sets of object from the DataSource.// <P>// The following visual components currently support databinding:<pre>// +link{class:DynamicForm}// +link{class:DetailViewer}// +link{class:ListGrid}// +link{class:TreeGrid}// +link{class:CubeGrid}// </pre>// The following non-visual components also support databinding:<pre>// +link{class:ValuesManager}// +link{class:ResultSet}// +link{class:ResultTree}// </pre>//// @treeLocation Client Reference/Data Binding// @visibility external//<// Currently the DataBinding APIs are present on all Canvii.// Documented as a separate, intervening class, to separate functionality (DataBoundComponent) isc.Canvas.addProperties({//> @attr dataBoundComponent.dataSource (DataSource or ID : null : IRW)// The DataSource that this component should bind to for default fields and for performing// +link{DSRequest,DataSource requests}.// <P>// Can be specified as either a DataSource instance or the String ID of a DataSource.//// @group databinding// @visibility external// @example dataSourceFields//< //> @attr dataBoundComponent.dataPageSize (number : 75 : IRW)// When using data paging, how many records to fetch at a time. The value of this// attribute is passed on to the auto-constructed +link{class:ResultSet} object for this// component. In effect, this gives you control over the +link{attr:ResultSet.resultSize}// attribute for this component.//// @group databinding// @see ResultSet.resultSize// @visibility external//< //> @attr dataBoundComponent.fields (Array of Field : null : IRW)// A DataBoundComponent manipulates records with one or more fields, and// <code>component.fields</code> tells the DataBoundComponent which fields to present, in what// order, and how to present each field.// <p>// When both <code>component.fields</code> and // <code>+link{dataBoundComponent.dataSource,component.dataSource}</code> are set,// any fields in <code>component.fields</code> with the same name as a DataSource field// inherit properties of the DataSource field. This allows you to centralize data model// information in the DataSource, but customize presentation of DataSource fields on a// per-component basic. For example, in a ListGrid, a shorter title or format for a field// might be chosen to save space.// <p>// By default, only fields specified on the component are shown, in the order specified on// the component. The +link{useAllDataSourceFields} flag can be set to show all fields// from the DataSource, with <code>component.fields</code> acting as field-by-field// overrides and/or additional fields.// <p>// If a DataBoundComponent is given a DataSource, but no <code>component.fields</code>, the// "default binding" is used: fields are shown in DataSource order, according// to the properties <code>+link{showHiddenFields}</code> and // <code>+link{showDetailFields}</code>.//// @group databinding// @visibility external// @example mergedFields// @example validationFieldBinding//<//> @attr dataBoundComponent.useAllDataSourceFields (boolean : false : IRW)// If true, the set of fields given by the "default binding" (see // +link{attr:DataBoundComponent.fields}) is used, with any fields specified in// <code>component.fields</code> acting as overrides that can suppress or modify the// display of individual fields, without having to list the entire set of fields that// should be shown.// <P>// If <code>component.fields</code> contains fields that are not found in the DataSource,// they will be shown after the most recently referred to DataSource field. If the new// fields appear first, they will be shown first.// <P>// +explorerExample{validationFieldBinding,This example} shows a mixture of component// fields and DataSource fields, and how they interact for validation.//// @group databinding// @visibility external// @example validationFieldBinding//<//> @attr dataBoundComponent.showHiddenFields (boolean : false : IRW)// Whether to show fields marked <code>hidden:true</code> when a DataBoundComponent is given a// DataSource but no <code>component.fields</code>.// <p>// The <code>hidden</code> property is used on DataSource fields to mark fields that are// never of meaning to an end user.// // @group databinding// @visibility external//<//> @attr dataBoundComponent.showDetailFields (boolean : false : IRW)// Whether to show include marked <code>detail:true</code> when a DataBoundComponent is // given a DataSource but no <code>component.fields</code>.// <p>// The <code>detail</code> property is used on DataSource fields to mark fields that // shouldn't appear by default in a view that tries to show many records in a small space.// // @group databinding// @visibility external//<//> @attr dataBoundComponent.showComplexFields (boolean : true : IRWA)// Whether to show fields of of non-atomic type when when a DataBoundComponent is given a// DataSource but no <code>component.fields</code>.// <p>// If true, the component will show fields that declare a complex type, for example, a// field 'shippingAddress' that declares type 'Address', where 'Address' is the ID of a// DataSource that declares the fields of a shipping address (city, street name, etc).// <P>// Such fields may need custom formatters or editors in order to create a usable interface,// for example, an Address field in a ListGrid might use a custom formatter to combine the// relevant fields of an address into one column, and might use a pop-up dialog for// editing.// // @group databinding// @visibility external//<showComplexFields:true,//> @attr dataBoundComponent.fetchOperation (String : null : IRW)// Operation ID this component should use when performing fetch operations.//// @see attr:DSRequest.operationId// @group operations// @visibility external//<//> @attr dataBoundComponent.updateOperation (String : null : IRW)// Operation ID this component should use when performing update operations.//// @see attr:DSRequest.operationId// @group operations// @visibility external//<//> @attr dataBoundComponent.addOperation (String : null : IRW)// Operation ID this component should use when performing add operations.//// @see attr:DSRequest.operationId// @group operations// @visibility external//<//> @attr dataBoundComponent.removeOperation (String : null : IRW)// Operation ID this component should use when performing remove operations.//// @see attr:DSRequest.operationId// @group operations// @visibility external//< // Property to be used as field identifier on field objects.// The ID of the field is also the property in each record which holds the value // for that field.fieldIdProperty:"name",//> @method dataBoundComponent.bindToDataSource()// Combine component's fields specifications with the fields specifications from the// datasource the component works with (specified indirectly by component.operation).// - check if fields property and dataSource property are specified// - if just dataSource, then use dataSource fields// - if just fields property, then default behavior// - if both, then use fields, with each field using defaults of dataSource<br>// calls setFields() when finished// @group data//<bindToDataSource : function (fields, componentIsDetail) { // Most components operate on a datasource, displaying or otherwise manipulating fields from // that datasource. We don't want to duplicate all the information about a field that is // specified in the datasource (type, title, etc) in each component that needs to display // that field. So, we allow the component's field specifications to refer to the datasource // field by name, and combine the field specification from the component with the field // specification from the datasource. // pick up the dataSource of our dataset if it has one and we weren't given one if (this.dataSource == null && this.data != null) this.dataSource = this.data.dataSource; // get the datasource versions of the field specifications. NOTE: this method may be // called in a build that does not include DataSource var ds = this.getDataSource(); if (ds != null && isc.isA.String(ds)) { this.logWarn("unable to look up DataSource: " + ds + ", databinding will not be used"); return fields; } // Shorthand - treat fields being null or an empty array as the same case - no (meaningful) // fields were passed in var noSpecifiedFields = (fields == null || fields.length == 0), dsFields; // get fields from the DataSource if we have one if (ds) { // flatten fields if so configured var flatten = this.useFlatFields; if (flatten == null) flatten = ds.useFlatFields; dsFields = flatten ? ds.getFlattenedFields() : ds.getFields(); } // Case 1: no dataSource specified // This widget isn't associated with a datasource - all fields are full specifications // intended for the underlying widget. The fields property is thus left untouched. if (ds == null || dsFields == null) { if (fields != null && isc.SimpleType) { // type defaults are auto-applied to DS fields and combined fields for (var i = 0; i < fields.length; i++) { isc.SimpleType.addTypeDefaults(fields[i]); } } return fields; } // Case 2: dataSource specified, but no fields specified // The widget will show all DataSource fields, applying reasonable defaults. if (ds != null && noSpecifiedFields) { // NOTE we generally have to create a copy of the DataSource fields rather than having // everyone use the same objects, because widgets tend to scribble things into this.fields, // such as widths derived by a sizing policy. fields = []; for (var fieldName in dsFields) { var field = dsFields[fieldName]; if (!this.shouldUseField(field, ds)) continue; fields.add(isc.addProperties({}, field)); } return fields; } // Case 3: dataSource and fields specified // fields provided to this instance act as an overlay on DataSource fields if (ds != null && !noSpecifiedFields) { if (this.useAllDataSourceFields) { var canvas = this; return ds.combineFieldOrders( dsFields, fields, function (field, ds) { return canvas.shouldUseField(field, ds) }); } else { // only the fields declared on the component will be shown, in the order specified on // the component for (var i = 0; i < fields.length; i++) { var field = fields[i]; if (!field) continue; var fieldName = field[this.fieldIdProperty]; // this field isn't a datasource field - it's just intended to be passed through // to the underlying widget (like a form spacer) // // always addTypeDefaults b/c local field spec may override field type // addTypeDefaults will bail immediately if it's already been applied isc.SimpleType.addTypeDefaults(field); if (!ds.getField(fieldName)) continue; // combine the component field specification with the datasource field // specification - component fields override so that you can eg, retitle a field // within a summary field = ds.combineFieldData(field); } // return the original fields array, with properties added to the field objects return fields; } }},// return whether this component wants to use the field when binding to a DataSourceshouldUseField : function (field, ds) { // hidden means don't show to an end user if (field.hidden && !this.showHiddenFields) return false; // don't use the field if the field is marked as a detail field and the component is not a // detail component if (field.detail && !this.showDetailFields) return false; if (!this.showComplexFields && ds.fieldIsComplexType(field.name)) return false; return true;},//> @method dataBoundComponent.getField() // Return the pointer to the field structure for a field by number//// @param fieldID (string || number) field number or value of this.fieldIdProperty//// @return (object) Field description// @group display//<getField : function (fieldId) { return isc.Class.getArrayItem(fieldId, this.fields, this.fieldIdProperty);},getFieldNum : function (fieldId) { return isc.Class.getArrayItemIndex(fieldId, this.fields, this.fieldIdProperty);},//> @method dataBoundComponent.setValueMap() // Set the valueMap for a field//// @param fieldID (number) number of field to update// @param map (object) ValueMap for the field////<setValueMap : function (field, map) { if (!isc.isAn.Object(field)) field = this.getField(field); if (!field) return; field.valueMap = map;},//> @method dataBoundComponent.setDataSource()// Bind to a new DataSource.// <P>// Like passing the "dataSource" property on creation, binding to a DataSource means that the// component will use the DataSource to provide default data for its fields.// <P>// When binding to a new DataSource, if the component has any existing "fields" or has a dataset,// these will be discarded by default, since it is assumed the new DataSource may represent a// completely unrelated set of objects. If the old "fields" are still relevant, pass them to// setDataSource().// // @param dataSource (ID or DataSource) DataSource to bind to // @param fields (Array of Fields) optional array of fields to use// // @visibility external// @example WSDLDataSource//<setDataSource : function (dataSource, fields) { if (isc._traceMarkers) arguments.__this = this; // if passed in value is null then bind() will then work on the declared ds. this.dataSource = dataSource || this.dataSource; // NOTE: actual dataBinding, meaning picking up dataSource field data, is done by // "bindToDataSource". This call *must* be within setFields() because setFields() may be // called againt after binding, and must pick up DataSource field data at that time too. if (this.setFields) this.setFields(fields); // since we've (re)bound this widget, clear any data it may have as it may no longer be // valid.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -