9

I am trying to create a simple ExtJS5 app against a Restful RubyonRails backend. For some reason when I instantiate a model ExtJs populates the "idProperty" field with the name of the model (and counter). e.g.

{"Traffic_id":"MyApp.model.Person-1","external_id":0,...

I thought the "idProperty" field is essentially the primary key of the data record and is normally set when the record is inserted in to the DB (autoincrement)

So this field should be null or similar as the model has yet to be added to the store and syncd to the backend.

Whats even more amaising is that the field is defined as 'int' and ExtJS puts a String in it!

Can someone tell me what is going on?

Peter

Below is an app.js to Fiddle with:

Ext.application({
    name : 'Fiddle',

    launch : function() {

        var model = Ext.create('MyApp.model.Person');

       Ext.Msg.alert('Fiddle', JSON.stringify(model.data));

    }
});

Ext.define('MyApp.model.Person', {
    extend: 'Ext.data.Model',
    idProperty: 'Traffic_id',

    proxy: {
        type: 'rest',
        // url: '/traffics.json',
        format: 'json',
        api: {
            create: 'traffics',
            read: 'traffics',
            update: 'traffics/edit',
            destroy: 'traffics'
        },

        reader: {
            type: 'json',
            rootProperty: 'traffic',
            successProperty: 'success',
            messageProperty: 'message'
        },
        writer: {
            type: 'json',
            //writeAllFields  : false,
            //encode: true,
            rootProperty: 'traffic'
        },
        afterRequest: function(req, res) {
            console.log("Ahoy!", req.operation.response);
        },
        listeners: {
            exception: function(proxy, response, operation) {
                //debugger;
                Ext.MessageBox.show({
                    title: 'XXX REMOTE EXCEPTION',
                    msg: operation.getError(),
                    icon: Ext.MessageBox.ERROR,
                    buttons: Ext.Msg.OK
                });
            }
        }
    },

    fields: [{
        name: 'Traffic_id',
        type: 'int'
    }, {
        name: 'external_id',
        type: 'int'
    }, {
        name: 'description',
        type: 'string'
    }, {
        name: 'insertUser',
        type: 'string'
    }, {
        name: 'insertDate',
        type: 'date'
    }]

});
Rhubarb65
  • 323
  • 2
  • 11
  • 2
    The "enhanced" model facility in ExtJs 5 is total junk -- this is just one of the many issues. There is no way to prevent it from assigning an id. The result is that your ID cannot be the ExtJS ID. – Dave Sep 25 '15 at 15:28

5 Answers5

2

Set config options: persist: false. When creating it will not send the value to the server. This option is useful when fields are used to keep state on the client but do not need to be persisted to the server.Ext.data.field.Field.persist

Ext.define('MyApp.model.Person', {
    extend: 'Ext.data.Model',
    idProperty: 'Traffic_id',
    fields: [{
        name: 'Traffic_id',
        type: 'int',
        persist: false
    }, {
        name: 'external_id',
        type: 'int'
    }, {
        name: 'description',
        type: 'string'
    }, {
        name: 'insertUser',
        type: 'string'
    }, {
        name: 'insertDate',
        type: 'date'
    }]
});
ajokn
  • 121
  • 1
  • 5
0

ExtJS assigns a "provisional" id to newly created models; it can distinguish between models that have been created client side that have not yet been saved ("phantom" models) vs ones that have been downloaded. As such, it knows when to call create vs update, and it will (I think, from memory) delete the ID when uploading to the create REST endpoint.

It needs the ID as the newly-created model can go into stores (e.g. for the Session, if nothing else).

The style of ID that you see is from the default sequential generator.

See http://docs.sencha.com/extjs/5.0/apidocs/#!/api/Ext.data.identifier.Generator for more.

Robert Watkins
  • 2,196
  • 15
  • 17
  • Just that it doesn't delete the ID when syncing models to the server via `create` endpoint in a json proxy. – Alexander Aug 15 '16 at 10:04
  • Does your endpoint return the new server-side id? The ``create`` operation processes the response and sets the ID if returned. See [http://docs.sencha.com/extjs/5.1.3/src/Operation.js.html#Ext.data.operation.Operation-method-doProcess] – Robert Watkins Aug 17 '16 at 12:37
  • Nope, the endpoint does not return the new server-side id - it throws 500 Internal Server Error because it expects the id value submitted as `"id":"ext-model-123"` to be an int. in earlier versions of the framework the id was unset for new records. I had an id property on the client side that was unique, yet I could submit multiple records to the server, and they all had id:"0" on the server side (default for int in C#), which told me that they were new and had to be created. I have helped myself in ExtJS6 by setting negative id values for new records in ExtJS. – Alexander Aug 17 '16 at 12:43
  • Well, ExtJS is doing what it's meant to do. Which isn't very helpful, I know. If you've got control over your endpoint, you should try and distinguish between POST (create a new record) vs PUT (update an existing one) - then the ExtJS assigned ID should be ignored on POST. Alternatively you can customise your proxy to make a ``create`` operation that filters the ID out so you don't send it. Or just use the negative values if that works for you. – Robert Watkins Aug 17 '16 at 12:53
0

Add another field with a calculate function and persist false to your model. Use this field in your View instead of your idProperty:

Ext.define('MyApp.model.MyModel', {
    extend: 'Ext.data.Model',

    requires: [
        'Ext.data.field.Integer',
        'Ext.data.field.String'
    ],

    idProperty: 'myId',

    fields: [
        {
            type: 'int',
            mapping: 'myId',
            name: 'myId'
        },
        {
            type: 'string',
            mapping: 'myName',
            name: 'myName'
        },
        {
            calculate: function(data) {
                if(!data) {
                    return '';
                }
                else {
                    return data.myId;
                }
            },
            name: 'myViewId',
            persist: false
        }
    ]
});
0

I did a workaround. After creation of model instance, set the id property to null.

var instance = Ext.create('MyModel');
instance.set('idProperty', null);
0

There are chances that you need to persist that option. There is one more option if you want to customize your id. Use identifier. The way I did it : Add the following code in your model.

identifier: {
        type: 'sequential',
        seed: 3
},
Avi
  • 2,014
  • 1
  • 9
  • 21