2017-11-23 1 views
1
양식 필드에

바인딩 모델 속성은 ExtJS로 꽤 쉽게 :이 경우사용 그리드는

// ...skipped everything until fields config for brevity 
}, { 
    xtype: 'textfield', 
    bind: '{modelInstance.someField}' 
}, { // ... 

modelInstance 문자열 필드 someField이 바인딩이 방법으로, 텍스트 상자 값 덕분에 동기화됩니다. 그리고 그것은 훌륭합니다.

모델 필드가 문자열이 아니라 배열 인 경우 동일한 종류의 동작을 얻으려고합니다.

// ...skipped everything until fields config for brevity, 
// assume that viewmodel and everything else are set up as expected 
}, { 
    xtype: 'textfield', 
    bind: '{modelInstance.easyField}' 
}, { 
    xtype: 'gridfield', 
    bind: { 
    gridArray: '{modelInstance.hardField}' 
    } 
}, { // ... 

는 당연히 내가 gridfield 구성 요소가 Ext.grid.Panel를 확장하고 modelInstance 필드 hardField에의 저장 데이터를 동기화 할 : 나는 같은 것을 할 싶습니다

Ext.define('namespace.model.CustomModel', { 
    fields: ['easyField', { 
    name: 'hardField', 
    type: 'auto' // This will be an array during runtime 
    }], 
    idProperty: 'easyField' 
}); 

:이 모델입니다. 방법

  • 가 어떻게 저장 gridArray 설정을 결합 할 내가 modelInstance.hardField 배열 gridFieldItems로 저장 초기 데이터를 기존의 주사 ​​않는

    • : 문제를 여기

      Ext.define('namespace.form.field.GridField', { 
          extends: 'Ext.grid.Panel', 
          xtype: 'gridfield', 
          // skip requires for brevity 
          viewModel: { 
          stores: { 
           gridFieldItems: { 
           type: 'gridfielditems' // Simple in memory store 
           } 
          }, 
          data: { 
          } 
          }, 
          store: '{gridFieldItems}', 
          // This config enables binding to take place as it creates getters and setters, 
          // gridArray is set initially to '{modelInstance.hardField}' as expected 
          config: { 
          gridArray: null 
          }, 
          // This is necessary for this grid-field component to update 
          // '{modelInstance.hardField}' back in the owners viewModel. 
          publishes: { 
          gridArray: true 
          }, 
      
          // ??? 
          // bind: { 
          // gridArray: bind gridArray to store data somehow? 
          // } 
      
      }); 
      

      것 : 현재

      나는이 있습니다 우리가 그리드를 따라 가면서 업데이트가되도록 데이터를 입력하십시오.

    • 이 모든 것을 우아한 MVV에서 수행하십시오 JS 객체간에 동기화를 시도하는 수많은 청취자를 작성하지 않고

    이미 잘 알려진 테스트 솔루션을 제공하십시오. 이미 많은 방법을 시도했지만, 지금까지 성공하지 못했습니다.

  • 답변

    0

    다음은이 바인딩을 구현하는 작업 방법입니다. 쉬운 방법은 배열 필드를 상점의 "데이터"속성으로 바인딩하는 것입니다. 작업에 대한 좋은 제안은 일반 구성 요소 (gridfield) 내에 뷰 모델을 정의하지 않고 응용 프로그램 별 뷰에서만 뷰 모델을 사용하는 것입니다. 일반 구성 요소에서는 setter/getter/update 논리를 사용하여 구성 속성 만 정의하여 바인드와 함께 사용할 수 있어야합니다. 이 경우 저장소가 충분하기 때문에 사용자 지정 속성이 필요하지 않습니다.

    편집 "쉬운 바인딩"을 피하기 위해 girdfield 구성 요소에 배열의 설정/가져 오기 논리를 구현할 수 있습니다. setter가 호출하는 "updateGridArray"메서드와 저장소의 "datachanged"이벤트를 사용하는 Fore 예제입니다. 바이올린이 업데이트되고 예제 Girdfield는 셀 편집 플러그인을 사용하여 양방향 바인딩을 표시합니다.

    바이올린 : https://fiddle.sencha.com/#view/editor&fiddle/2a3b

    Ext.define('Fiddle.model.CustomModel', { 
         extend: 'Ext.data.Model', 
         fields: ['easyField', { 
          name: 'hardField', 
          type: 'auto' // This will be an array during runtime 
         }], 
         idProperty: 'easyField' 
        }); 
        Ext.define('Fiddle.fiddleview.CustomViewModel', { 
         extend: 'Ext.app.ViewModel', 
         alias: 'viewmodel.fiddleview', 
    
         data: { 
          currentModel: null 
         } 
        }); 
        Ext.define('Fiddle.form.field.GridField', { 
         extend: 'Ext.grid.Panel', 
         xtype: 'gridfield', 
    
         config: { 
          gridArray: null 
         }, 
    
         publishes: [ 
          'selection', 
          'gridArray' 
         ], 
    
         selModel: 'cellmodel', 
         plugins: { 
          cellediting: { 
           clicksToEdit: 1 
          } 
         }, 
    
         columns: [{ 
          text: 'Column 1', 
          flex: 1, 
          editor: true, 
          dataIndex: 'field1' 
         }], 
    
         initComponent: function() { 
          this.store = { 
           fields: ['field1'], 
           data: [], 
           listeners: { 
            scope: this, 
            datachanged: function (store) { 
             this.setGridArray(store.getRange().map(function (record) { 
              return record.getData(); 
             })); 
            } 
           } 
          }; 
    
          this.callParent(); 
         }, 
    
         updateGridArray: function (gridArray) { 
          this.getStore().suspendEvent('datachanged'); 
          if (Ext.isEmpty(gridArray)) { 
           this.getStore().removeAll(); 
          } else { 
           this.getStore().loadData(gridArray); 
          } 
          this.getStore().resumeEvent('datachanged'); 
         } 
    
        }); 
    
        var myView = Ext.create('Ext.container.Container', { 
         renderTo: Ext.getBody(), 
    
         viewModel: 'fiddleview', 
    
         items: [{ 
          xtype: 'gridfield', 
          bind: { 
           gridArray: '{currentModel.hardField}' 
          } 
         }] 
        }); 
    
        // Bind on model's array to check two-way update 
        // It will execute also on cell edit 
        myView.getViewModel().bind('{currentModel.hardField}', function (value) { 
         window.alert('model\'s array changed'); 
        }); 
    
        // The binding is now active, when the "currentModel" in the viewmodel changes, grid rows are refresched 
        myView.getViewModel().set('currentModel', new Fiddle.model.CustomModel({ 
         hardField: [{ 
          field1: 'value1' 
         }] 
        })); 
        // Also when data changes in the "currentModel" 
        myView.getViewModel().get('currentModel').get('hardField').push({ 
         field1: 'value2' 
        }); 
    
    +0

    감사 남작! 상점 데이터를 모델 필드에 바인딩한다는 아이디어는 훌륭하지만 결함이 있습니다. 우리는 저장소가 그리드 저장소가 아닌 원본 모델 배열의 레코드를 업데이트 할 수밖에 없습니다. 왜냐하면 저장소가 업데이트를 모델로 다시 푸시하지 않기 때문입니다. 이는 그리드가 그 일반성을 깨뜨리는 뷰 모델에 대한 지식을 가져야 함을 의미합니다. 게다가, 사용자에게 추가/업데이트보기를 제공하는 방법을 알지 못합니다. 나중에 내 솔루션을 게시 할 예정이지만, 이상적이지는 않지만 목적 상 괜찮을 것입니다. –

    +0

    당신 말이 맞아요. 그것은 깨끗한 바인드 솔루션이었습니다. 바인드 가능 구성으로 "gridArray"만 필요한 "gridfield"구성 요소로 바이올린을 업데이트했습니다. –