123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778 |
- <!DOCTYPE html>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>The source code</title>
- <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
- <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
- <style type="text/css">
- .highlight { display: block; background-color: #ddd; }
- </style>
- <script type="text/javascript">
- function highlight() {
- document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
- }
- </script>
- </head>
- <body onload="prettyPrint(); highlight();">
- <pre class="prettyprint lang-js"><span id='Ext-data-reader-Reader'>/**
- </span> * @author Ed Spencer
- *
- * Readers are used to interpret data to be loaded into a {@link Ext.data.Model Model} instance or a {@link
- * Ext.data.Store Store} - often in response to an AJAX request. In general there is usually no need to create
- * a Reader instance directly, since a Reader is almost always used together with a {@link Ext.data.proxy.Proxy Proxy},
- * and is configured using the Proxy's {@link Ext.data.proxy.Proxy#cfg-reader reader} configuration property:
- *
- * Ext.create('Ext.data.Store', {
- * model: 'User',
- * proxy: {
- * type: 'ajax',
- * url : 'users.json',
- * reader: {
- * type: 'json',
- * root: 'users'
- * }
- * },
- * });
- *
- * The above reader is configured to consume a JSON string that looks something like this:
- *
- * {
- * "success": true,
- * "users": [
- * { "name": "User 1" },
- * { "name": "User 2" }
- * ]
- * }
- *
- *
- * # Loading Nested Data
- *
- * Readers have the ability to automatically load deeply-nested data objects based on the {@link Ext.data.association.Association
- * associations} configured on each Model. Below is an example demonstrating the flexibility of these associations in a
- * fictional CRM system which manages a User, their Orders, OrderItems and Products. First we'll define the models:
- *
- * Ext.define("User", {
- * extend: 'Ext.data.Model',
- * fields: [
- * 'id', 'name'
- * ],
- *
- * hasMany: {model: 'Order', name: 'orders'},
- *
- * proxy: {
- * type: 'rest',
- * url : 'users.json',
- * reader: {
- * type: 'json',
- * root: 'users'
- * }
- * }
- * });
- *
- * Ext.define("Order", {
- * extend: 'Ext.data.Model',
- * fields: [
- * 'id', 'total'
- * ],
- *
- * hasMany : {model: 'OrderItem', name: 'orderItems', associationKey: 'order_items'},
- * belongsTo: 'User'
- * });
- *
- * Ext.define("OrderItem", {
- * extend: 'Ext.data.Model',
- * fields: [
- * 'id', 'price', 'quantity', 'order_id', 'product_id'
- * ],
- *
- * belongsTo: ['Order', {model: 'Product', associationKey: 'product'}]
- * });
- *
- * Ext.define("Product", {
- * extend: 'Ext.data.Model',
- * fields: [
- * 'id', 'name'
- * ],
- *
- * hasMany: 'OrderItem'
- * });
- *
- * This may be a lot to take in - basically a User has many Orders, each of which is composed of several OrderItems.
- * Finally, each OrderItem has a single Product. This allows us to consume data like this:
- *
- * {
- * "users": [
- * {
- * "id": 123,
- * "name": "Ed",
- * "orders": [
- * {
- * "id": 50,
- * "total": 100,
- * "order_items": [
- * {
- * "id" : 20,
- * "price" : 40,
- * "quantity": 2,
- * "product" : {
- * "id": 1000,
- * "name": "MacBook Pro"
- * }
- * },
- * {
- * "id" : 21,
- * "price" : 20,
- * "quantity": 3,
- * "product" : {
- * "id": 1001,
- * "name": "iPhone"
- * }
- * }
- * ]
- * }
- * ]
- * }
- * ]
- * }
- *
- * The JSON response is deeply nested - it returns all Users (in this case just 1 for simplicity's sake), all of the
- * Orders for each User (again just 1 in this case), all of the OrderItems for each Order (2 order items in this case),
- * and finally the Product associated with each OrderItem. Now we can read the data and use it as follows:
- *
- * var store = Ext.create('Ext.data.Store', {
- * model: "User"
- * });
- *
- * store.load({
- * callback: function() {
- * //the user that was loaded
- * var user = store.first();
- *
- * console.log("Orders for " + user.get('name') + ":")
- *
- * //iterate over the Orders for each User
- * user.orders().each(function(order) {
- * console.log("Order ID: " + order.getId() + ", which contains items:");
- *
- * //iterate over the OrderItems for each Order
- * order.orderItems().each(function(orderItem) {
- * //we know that the Product data is already loaded, so we can use the synchronous getProduct
- * //usually, we would use the asynchronous version (see {@link Ext.data.association.BelongsTo})
- * var product = orderItem.getProduct();
- *
- * console.log(orderItem.get('quantity') + ' orders of ' + product.get('name'));
- * });
- * });
- * }
- * });
- *
- * Running the code above results in the following:
- *
- * Orders for Ed:
- * Order ID: 50, which contains items:
- * 2 orders of MacBook Pro
- * 3 orders of iPhone
- */
- Ext.define('Ext.data.reader.Reader', {
- requires: ['Ext.data.ResultSet', 'Ext.XTemplate'],
- alternateClassName: ['Ext.data.Reader', 'Ext.data.DataReader'],
- mixins: {
- observable: 'Ext.util.Observable'
- },
- <span id='Ext-data-reader-Reader-cfg-idProperty'> /**
- </span> * @cfg {String} idProperty
- * Name of the property within a row object that contains a record identifier value. Defaults to the id of the
- * model. If an idProperty is explicitly specified it will override the idProperty defined on the model.
- */
- <span id='Ext-data-reader-Reader-cfg-totalProperty'> /**
- </span> * @cfg {String} [totalProperty="total"]
- * Name of the property from which to retrieve the total number of records in the dataset. This is only needed if
- * the whole dataset is not passed in one go, but is being paged from the remote server.
- */
- totalProperty: 'total',
- <span id='Ext-data-reader-Reader-cfg-successProperty'> /**
- </span> * @cfg {String} [successProperty="success"]
- * Name of the property from which to retrieve the `success` attribute, the value of which indicates
- * whether a given request succeeded or failed (typically a boolean or 'true'|'false'). See
- * {@link Ext.data.proxy.Server}.{@link Ext.data.proxy.Server#exception exception} for additional information.
- */
- successProperty: 'success',
- <span id='Ext-data-reader-Reader-cfg-root'> /**
- </span> * @cfg {String} root
- * The name of the property which contains the data items corresponding to the Model(s) for which this
- * Reader is configured. For JSON reader it's a property name (or a dot-separated list of property names
- * if the root is nested). For XML reader it's a CSS selector. For Array reader the root is not applicable
- * since the data is assumed to be a single-level array of arrays.
- *
- * By default the natural root of the data will be used: the root JSON array, the root XML element, or the array.
- *
- * The data packet value for this property should be an empty array to clear the data or show no data.
- */
- root: '',
-
- <span id='Ext-data-reader-Reader-cfg-messageProperty'> /**
- </span> * @cfg {String} messageProperty
- * The name of the property which contains a response message. This property is optional.
- */
-
- <span id='Ext-data-reader-Reader-cfg-implicitIncludes'> /**
- </span> * @cfg {Boolean} [implicitIncludes=true]
- * True to automatically parse models nested within other models in a response object. See the
- * Ext.data.reader.Reader intro docs for full explanation.
- */
- implicitIncludes: true,
-
- <span id='Ext-data-reader-Reader-cfg-readRecordsOnFailure'> /**
- </span> * @cfg {Boolean} [readRecordsOnFailure=true]
- * True to extract the records from a data packet even if the {@link #successProperty} returns false.
- */
- readRecordsOnFailure: true,
-
- <span id='Ext-data-reader-Reader-property-metaData'> /**
- </span> * @property {Object} metaData
- * The raw meta data that was most recently read, if any. Meta data can include existing
- * Reader config options like {@link #idProperty}, {@link #totalProperty}, etc. that get
- * automatically applied to the Reader, and those can still be accessed directly from the Reader
- * if needed. However, meta data is also often used to pass other custom data to be processed
- * by application code. For example, it is common when reconfiguring the data model of a grid to
- * also pass a corresponding column model config to be applied to the grid. Any such data will
- * not get applied to the Reader directly (it just gets passed through and is ignored by Ext).
- * This metaData property gives you access to all meta data that was passed, including any such
- * custom data ignored by the reader.
- *
- * This is a read-only property, and it will get replaced each time a new meta data object is
- * passed to the reader. Note that typically you would handle proxy's
- * {@link Ext.data.proxy.Proxy#metachange metachange} event which passes this exact same meta
- * object to listeners. However this property is available if it's more convenient to access it
- * via the reader directly in certain cases.
- * @readonly
- */
-
- /*
- * @property {Boolean} isReader
- * `true` in this class to identify an object as an instantiated Reader, or subclass thereof.
- */
- isReader: true,
- // Private flag to the generated convertRecordData function to indicate whether to apply Field default
- // values to fields for which no value is present in the raw data.
- // This is set to false by a Server Proxy which is reading the response from a "create" or "update" operation.
- applyDefaults: true,
- lastFieldGeneration: null,
-
- <span id='Ext-data-reader-Reader-method-constructor'> /**
- </span> * Creates new Reader.
- * @param {Object} config (optional) Config object.
- */
- constructor: function(config) {
- var me = this;
-
- me.mixins.observable.constructor.call(me, config);
- me.fieldCount = 0;
- me.model = Ext.ModelManager.getModel(me.model);
- me.accessExpressionFn = Ext.Function.bind(me.createFieldAccessExpression, me);
- // Extractors can only be calculated if the fields MixedCollection has been set.
- // A Model may only complete its setup (set the prototype properties) after asynchronous loading
- // which would mean that there may be no "fields"
- // If this happens, the load callback will call proxy.setModel which calls reader.setModel which
- // triggers buildExtractors.
- if (me.model && me.model.prototype.fields) {
- me.buildExtractors();
- }
- this.addEvents(
- <span id='Ext-data-reader-Reader-event-exception'> /**
- </span> * @event
- * Fires when the reader receives improperly encoded data from the server
- * @param {Ext.data.reader.Reader} reader A reference to this reader
- * @param {XMLHttpRequest} response The XMLHttpRequest response object
- * @param {Ext.data.ResultSet} error The error object
- */
- 'exception'
- );
- },
- <span id='Ext-data-reader-Reader-method-setModel'> /**
- </span> * Sets a new model for the reader.
- * @private
- * @param {Object} model The model to set.
- * @param {Boolean} setOnProxy True to also set on the Proxy, if one is configured
- */
- setModel: function(model, setOnProxy) {
- var me = this;
-
- me.model = Ext.ModelManager.getModel(model);
- me.buildExtractors(true);
-
- if (setOnProxy && me.proxy) {
- me.proxy.setModel(me.model, true);
- }
- },
- <span id='Ext-data-reader-Reader-method-read'> /**
- </span> * Reads the given response object. This method normalizes the different types of response object that may be passed to it.
- * If it's an XMLHttpRequest object, hand off to the subclass' {@link #getResponseData} method.
- * Else, hand off the reading of records to the {@link #readRecords} method.
- * @param {Object} response The response object. This may be either an XMLHttpRequest object or a plain JS object
- * @return {Ext.data.ResultSet} The parsed or default ResultSet object
- */
- read: function(response) {
- var data;
- if (response) {
- data = response.responseText ? this.getResponseData(response) : this.readRecords(response);
- }
- return data || this.nullResultSet;
- },
- <span id='Ext-data-reader-Reader-method-readRecords'> /**
- </span> * Abstracts common functionality used by all Reader subclasses. Each subclass is expected to call this function
- * before running its own logic and returning the Ext.data.ResultSet instance. For most Readers additional
- * processing should not be needed.
- * @param {Object} data The raw data object
- * @return {Ext.data.ResultSet} A ResultSet object
- */
- readRecords: function(data) {
- var me = this,
- success,
- recordCount,
- records,
- root,
- total,
- value,
- message;
-
- /*
- * We check here whether fields collection has changed since the last read.
- * This works around an issue when a Model is used for both a Tree and another
- * source, because the tree decorates the model with extra fields and it causes
- * issues because the readers aren't notified.
- */
- if (me.lastFieldGeneration !== me.model.prototype.fields.generation) {
- me.buildExtractors(true);
- }
-
- <span id='Ext-data-reader-Reader-property-rawData'> /**
- </span> * @property {Object} rawData
- * The raw data object that was last passed to {@link #readRecords}. Stored for further processing if needed.
- */
- me.rawData = data;
- data = me.getData(data);
-
- success = true;
- recordCount = 0;
- records = [];
-
- if (me.successProperty) {
- value = me.getSuccess(data);
- if (value === false || value === 'false') {
- success = false;
- }
- }
-
- if (me.messageProperty) {
- message = me.getMessage(data);
- }
-
- // Only try and extract other data if call was successful
- if (me.readRecordsOnFailure || success) {
- // If we pass an array as the data, we dont use getRoot on the data.
- // Instead the root equals to the data.
- root = Ext.isArray(data) ? data : me.getRoot(data);
-
- if (root) {
- total = root.length;
- }
- if (me.totalProperty) {
- value = parseInt(me.getTotal(data), 10);
- if (!isNaN(value)) {
- total = value;
- }
- }
- if (root) {
- records = me.extractData(root);
- recordCount = records.length;
- }
- }
- return new Ext.data.ResultSet({
- total : total || recordCount,
- count : recordCount,
- records: records,
- success: success,
- message: message
- });
- },
- <span id='Ext-data-reader-Reader-method-extractData'> /**
- </span> * Returns extracted, type-cast rows of data.
- * @param {Object[]/Object} root from server response
- * @return {Array} An array of records containing the extracted data
- * @private
- */
- extractData : function(root) {
- var me = this,
- records = [],
- Model = me.model,
- length = root.length,
- convertedValues, node, record, i;
-
- if (!root.length && Ext.isObject(root)) {
- root = [root];
- length = 1;
- }
- for (i = 0; i < length; i++) {
- node = root[i];
- if (!node.isModel) {
- // Create a record with an empty data object.
- // Populate that data object by extracting and converting field values from raw data
- record = new Model(undefined, me.getId(node), node, convertedValues = {});
- // If the server did not include an id in the response data, the Model constructor will mark the record as phantom.
- // We need to set phantom to false here because records created from a server response using a reader by definition are not phantom records.
- record.phantom = false;
- // Use generated function to extract all fields at once
- me.convertRecordData(convertedValues, node, record);
- records.push(record);
-
- if (me.implicitIncludes) {
- me.readAssociated(record, node);
- }
- } else {
- // If we're given a model instance in the data, just push it on
- // without doing any conversion
- records.push(node);
- }
- }
- return records;
- },
-
- <span id='Ext-data-reader-Reader-method-readAssociated'> /**
- </span> * @private
- * Loads a record's associations from the data object. This prepopulates hasMany and belongsTo associations
- * on the record provided.
- * @param {Ext.data.Model} record The record to load associations for
- * @param {Object} data The data object
- * @return {String} Return value description
- */
- readAssociated: function(record, data) {
- var associations = record.associations.items,
- i = 0,
- length = associations.length,
- association, associationData, proxy, reader;
-
- for (; i < length; i++) {
- association = associations[i];
- associationData = this.getAssociatedDataRoot(data, association.associationKey || association.name);
-
- if (associationData) {
- reader = association.getReader();
- if (!reader) {
- proxy = association.associatedModel.proxy;
- // if the associated model has a Reader already, use that, otherwise attempt to create a sensible one
- if (proxy) {
- reader = proxy.getReader();
- } else {
- reader = new this.constructor({
- model: association.associatedName
- });
- }
- }
- association.read(record, reader, associationData);
- }
- }
- },
-
- <span id='Ext-data-reader-Reader-method-getAssociatedDataRoot'> /**
- </span> * @private
- * Used internally by {@link #readAssociated}. Given a data object (which could be json, xml etc) for a specific
- * record, this should return the relevant part of that data for the given association name. This is only really
- * needed to support the XML Reader, which has to do a query to get the associated data object
- * @param {Object} data The raw data object
- * @param {String} associationName The name of the association to get data for (uses associationKey if present)
- * @return {Object} The root
- */
- getAssociatedDataRoot: function(data, associationName) {
- return data[associationName];
- },
-
- getFields: function() {
- return this.model.prototype.fields.items;
- },
- <span id='Ext-data-reader-Reader-method-getData'> /**
- </span> * @private
- * By default this function just returns what is passed to it. It can be overridden in a subclass
- * to return something else. See XmlReader for an example.
- * @param {Object} data The data object
- * @return {Object} The normalized data object
- */
- getData: function(data) {
- return data;
- },
- <span id='Ext-data-reader-Reader-method-getRoot'> /**
- </span> * @private
- * This will usually need to be implemented in a subclass. Given a generic data object (the type depends on the type
- * of data we are reading), this function should return the object as configured by the Reader's 'root' meta data config.
- * See XmlReader's getRoot implementation for an example. By default the same data object will simply be returned.
- * @param {Object} data The data object
- * @return {Object} The same data object
- */
- getRoot: function(data) {
- return data;
- },
- <span id='Ext-data-reader-Reader-method-getResponseData'> /**
- </span> * Takes a raw response object (as passed to the {@link #read} method) and returns the useful data
- * segment from it. This must be implemented by each subclass.
- * @param {Object} response The response object
- * @return {Ext.data.ResultSet} A ResultSet object
- */
- getResponseData: function(response) {
- //<debug>
- Ext.Error.raise("getResponseData must be implemented in the Ext.data.reader.Reader subclass");
- //</debug>
- },
- <span id='Ext-data-reader-Reader-method-onMetaChange'> /**
- </span> * @private
- * Reconfigures the meta data tied to this Reader
- */
- onMetaChange : function(meta) {
- var me = this,
- fields = meta.fields || me.getFields(),
- newModel,
- clientIdProperty;
-
- // save off the raw meta data
- me.metaData = meta;
-
- // set any reader-specific configs from meta if available
- me.root = meta.root || me.root;
- me.idProperty = meta.idProperty || me.idProperty;
- me.totalProperty = meta.totalProperty || me.totalProperty;
- me.successProperty = meta.successProperty || me.successProperty;
- me.messageProperty = meta.messageProperty || me.messageProperty;
- clientIdProperty = meta.clientIdProperty;
- if (me.model) {
- me.model.setFields(fields, me.idProperty, clientIdProperty);
- me.setModel(me.model, true);
- }
- else {
- newModel = Ext.define("Ext.data.reader.Json-Model" + Ext.id(), {
- extend: 'Ext.data.Model',
- fields: fields,
- clientIdProperty: clientIdProperty
- });
- if (me.idProperty) {
- // We only do this if the reader actually has a custom idProperty set,
- // otherwise let the model use its own default value. It is valid for
- // the reader idProperty to be undefined, in which case it will use the
- // model's idProperty (in getIdProperty()).
- newModel.idProperty = me.idProperty;
- }
- me.setModel(newModel, true);
- }
- },
-
- <span id='Ext-data-reader-Reader-method-getIdProperty'> /**
- </span> * Get the idProperty to use for extracting data
- * @private
- * @return {String} The id property
- */
- getIdProperty: function(){
- return this.idProperty || this.model.prototype.idProperty;
- },
- <span id='Ext-data-reader-Reader-method-buildExtractors'> /**
- </span> * @private
- * This builds optimized functions for retrieving record data and meta data from an object.
- * Subclasses may need to implement their own getRoot function.
- * @param {Boolean} [force=false] True to automatically remove existing extractor functions first
- */
- buildExtractors: function(force) {
- var me = this,
- idProp = me.getIdProperty(),
- totalProp = me.totalProperty,
- successProp = me.successProperty,
- messageProp = me.messageProperty,
- accessor,
- idField,
- map;
-
- if (force === true) {
- delete me.convertRecordData;
- }
-
- if (me.convertRecordData) {
- return;
- }
- //build the extractors for all the meta data
- if (totalProp) {
- me.getTotal = me.createAccessor(totalProp);
- }
- if (successProp) {
- me.getSuccess = me.createAccessor(successProp);
- }
- if (messageProp) {
- me.getMessage = me.createAccessor(messageProp);
- }
- if (idProp) {
- idField = me.model.prototype.fields.get(idProp);
- if (idField) {
- map = idField.mapping;
- idProp = (map !== undefined && map !== null) ? map : idProp;
- }
- accessor = me.createAccessor(idProp);
- me.getId = function(record) {
- var id = accessor.call(me, record);
- return (id === undefined || id === '') ? null : id;
- };
- } else {
- me.getId = function() {
- return null;
- };
- }
- me.convertRecordData = me.buildRecordDataExtractor();
- me.lastFieldGeneration = me.model.prototype.fields.generation;
- },
- recordDataExtractorTemplate : [
- 'var me = this\n',
- ' ,fields = me.model.prototype.fields\n',
- ' ,value\n',
- ' ,internalId\n',
- '<tpl for="fields">',
- ' ,__field{#} = fields.get("{name}")\n',
- '</tpl>', ';\n',
- 'return function(dest, source, record) {\n',
- '<tpl for="fields">',
- // createFieldAccessExpression must be implemented in subclasses to extract data from the source object in the correct way
- ' value = {[ this.createFieldAccessExpression(values, "__field" + xindex, "source") ]};\n',
- // Code for processing a source property when a custom convert is defined
- '<tpl if="hasCustomConvert">',
- ' dest["{name}"] = value === undefined ? __field{#}.convert(__field{#}.defaultValue, record) : __field{#}.convert(value, record);\n',
- // Code for processing a source property when there is a default value
- '<tpl elseif="defaultValue !== undefined">',
- ' if (value === undefined) {\n',
- ' if (me.applyDefaults) {\n',
- '<tpl if="convert">',
- ' dest["{name}"] = __field{#}.convert(__field{#}.defaultValue, record);\n',
- '<tpl else>',
- ' dest["{name}"] = __field{#}.defaultValue\n',
- '</tpl>',
- ' };\n',
- ' } else {\n',
- '<tpl if="convert">',
- ' dest["{name}"] = __field{#}.convert(value, record);\n',
- '<tpl else>',
- ' dest["{name}"] = value;\n',
- '</tpl>',
- ' };',
- // Code for processing a source property value when there is no default value
- '<tpl else>',
- ' if (value !== undefined) {\n',
- '<tpl if="convert">',
- ' dest["{name}"] = __field{#}.convert(value, record);\n',
- '<tpl else>',
- ' dest["{name}"] = value;\n',
- '</tpl>',
- ' }\n',
- '</tpl>',
- '</tpl>',
- // set the client id as the internalId of the record.
- // clientId handles the case where a client side record did not previously exist on the server,
- // so the server is passing back a client id that can be used to pair the server side record up with the client record
- '<tpl if="clientIdProp">',
- ' if (record && (internalId = {[ this.createFieldAccessExpression(\{mapping: values.clientIdProp\}, null, "source") ]})) {\n',
- ' record.{["internalId"]} = internalId;\n',
- ' }\n',
- '</tpl>',
- '};'
- ],
- <span id='Ext-data-reader-Reader-method-buildRecordDataExtractor'> /**
- </span> * @private
- * Return a function which will read a raw row object in the format this Reader accepts, and populates
- * a record's data object with converted data values.
- *
- * The returned function must be passed the following parameters:
- *
- * - dest A record's empty data object into which the new field value properties are injected.
- * - source A raw row data object of whatever type this Reader consumes
- * - record The record which is being populated.
- *
- */
- buildRecordDataExtractor: function() {
- var me = this,
- modelProto = me.model.prototype,
- templateData = {
- clientIdProp: modelProto.clientIdProperty,
- fields: modelProto.fields.items
- };
- me.recordDataExtractorTemplate.createFieldAccessExpression = me.accessExpressionFn;
- // Here we are creating a new Function and invoking it immediately in the scope of this Reader
- // It declares several vars capturing the configured context of this Reader, and returns a function
- // which, when passed a record data object, a raw data row in the format this Reader is configured to read,
- // and the record which is being created, will populate the record's data object from the raw row data.
- return Ext.functionFactory(me.recordDataExtractorTemplate.apply(templateData)).call(me);
- },
- destroyReader: function() {
- var me = this;
- delete me.proxy;
- delete me.model;
- delete me.convertRecordData;
- delete me.getId;
- delete me.getTotal;
- delete me.getSuccess;
- delete me.getMessage;
- }
- }, function() {
- var proto = this.prototype;
- Ext.apply(proto, {
- // Private. Empty ResultSet to return when response is falsy (null|undefined|empty string)
- nullResultSet: new Ext.data.ResultSet({
- total : 0,
- count : 0,
- records: [],
- success: true
- }),
- recordDataExtractorTemplate: new Ext.XTemplate(proto.recordDataExtractorTemplate)
- });
- });
- </pre>
- </body>
- </html>
|