Results 1 to 4 of 4

Thread: [OPEN-125] Store (using AjaxProxy) duplicates new record when .sync() is called

    Thank you for reporting this bug. We will make it our priority to review this report.
  1. #1
    Sencha User
    Join Date
    May 2011
    Vote Rating

    Lightbulb [OPEN-125] Store (using AjaxProxy) duplicates new record when .sync() is called

    Sencha Touch version tested:
    • 1.1.0

    Platform tested against:
    • iOS 4
    • Android 2.1

    • New records are duplicated in a store after .sync() is called, when using an AjaxProxy.

    Test Case:

    // models/contact.js
      app.models.Contact = new Ext.regModel('Contact', {
        fields: [
          { name: 'id', type: 'int' },
          { name: 'first_name', type: 'string' },
          { name: 'last_name', type: 'string' },
          { name: 'email', type: 'string' },
          { name: 'phone', type: 'string' }
        validations: [
          { type: 'presence', field: 'first_name', message: 'none' },
          { type: 'presence', field: 'last_name', message: 'none' },
          { type: 'email', field: 'email', message: 'Please enter a valid e-mail address.' },
          { type: 'phone', field: 'phone', message: 'Please enter a valid phone number.'}
        proxy: {
          type: 'ajax',
          url: 'contacts.xml',
          reader: {
            type: 'xml',
            record: 'contact'
          writer: {
            type: 'xml',
            record: 'contact'
      Ext.regStore('contacts', {
        autoLoad: true,
        model: 'Contact',
        sorters: ['last_name'],
        sortOnLoad: true,
        getGroupString : function(record) {
            return (record.get('last_name') || '#')[0].toUpperCase();
    // in views/contacts/list.js
      app.views.ContactsList = Ext.extend(Ext.Panel, {
        title: 'Contacts',
        layout: 'fit',
        store: 'contacts',
        initComponent: function () {  
          this.list = new Ext.List({
            xtype: 'list',
            id: 'contactslist',
            grouped: true,
            indexBar: true,
            itemTpl: '{first_name} <strong>{last_name}</strong>'
          this.items = [this.list];
          app.views.ContactsList.superclass.initComponent.apply(this, arguments);
      Ext.reg('contacts/list', app.views.ContactsList);
    // in controller:
      var contact = Ext.ModelMgr.create(this.form.getValues(), 'Contact');
      var store = Ext.getStore('contacts');
      store.sync(); // Duplicate appears in views list once .sync() asynchronously completes.
    Steps to reproduce the problem:
    • Attach a store (backed by an AjaxProxy) to a list
    • Add a new (unsaved) record to the same store
    • Call .sync() on store

    The result that was expected:
    • List should reflect one new item in the store

    The result that occurs instead:
    • List shows the new item twice

    Debugging already done:
    • Determined that the record returned from the server is never matched against the existing record in the store - because the internalId doesn't match.

    Possible fix:
    • Please see this commit on github for my change to AjaxProxy.js which fixes this for me.
    • Note that the list isn't sorted properly within each group after my fix, but that might be the fault of the way I'm sorting things at the moment.
    Last edited by mark.haylock; 30 May 2011 at 1:45 PM. Reason: Accidentally submitted the post instead of previewing, so had to complete the post! Sorry.

  2. #2
    Sencha User
    Join Date
    May 2011
    Vote Rating

    Default Questions about bug fixing process and support licenses

    We are currently evaluating Sencha Touch as a platform to move forward with and I've been playing around getting a feel for it's capabilities.

    We are pretty keen on what we have seen and will likely purchase a support license, however this duplicate problem caused me some grey hairs, so I have some questions I hope can be answered:

    1. Is this a bug or have I set up things incorrectly?
    2. If this is a bug is it fixed in the version available only to support licensees? Is there any public information about what is in the version available only to support licensees?
    3. If this bug is not fixed in the version available to support licensees then what would be the normal turnaround for such a bug fix to become available (if we had a support license)?
    4. I notice that in this post you mention "If we get demand for a github repository featuring just the public releases we may set that up too" - can I add a vote for that? It seems that would make submitting fixes like this easier for both sides if we could generate pull requests on github.

  3. #3
    Ext JS Premium Member christocracy's Avatar
    Join Date
    Oct 2006
    Vote Rating

    Default I noticed this issue too

    I experience this issue as well and tracked down the problem.

    It's a bug.

    Perhaps this override might help someone. It worked for me and my RestProxy.

    Basically, when the DataReader reads a response back from server, it instantiates new record instances, with new internalId set.

    When the store has its onWrite callback fired, it tries to replace the original record (which caused the CREATE/UPDATE action) with the new version from server, but it can't possibly find it unless their internalId are set the same.
    onProxyWrite: function(operation) {
            var data     =,
                action   = operation.action,
                records  = operation.getRecords(),
                length   = records.length,
                callback = operation.callback,
                record, i;
            if (operation.wasSuccessful()) {
                if (action == 'create' || action == 'update') {
                    for (i = 0; i < length; i++) {
                        record = records[i];
                        record.phantom = false;
                        data.replace(record);  // <-- HERE.  Store tries to replace oldRec with newRec.
                else if (action == 'destroy') {
                    for (i = 0; i < length; i++) {
                        record = records[i];
                    this.removed = [];
            //this is a callback that would have been passed to the 'create', 'update' or 'destroy' function and is optional
            if (typeof callback == 'function') {
       || this, records, operation, operation.wasSuccessful());
    * @author Chris Scott
    * @business
    * @rate $150USD / hr; training $500USD / day / developer (5 dev min)
    * @SenchaDevs
    * @twitter!/christocracy
    * @github

  4. #4
    Sencha User edspencer's Avatar
    Join Date
    Jan 2009
    Palo Alto, California
    Vote Rating


    This is a recurring issue with the architecture around creating Model instances locally and saving them remotely. At the moment it's rather difficult to accurately match each record returned by the server against the record we sent to the server.

    We're formulating a better solution to this internally at the moment and will keep you updated.
    Ext JS Senior Software Architect
    Personal Blog:

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts