2014-05-22 5 views
0

범위 문제에 대해 조금은 조사했지만 몇 가지 발견했지만 제 경우에는 잘 작동하지 않습니다. 나는 정말로 atm을 혼란스럽게 생각하기 때문에 나는 포럼에 직접 물을 수도 있다고 생각했다.ExtJS의 범위 함수 핸들러 내부

나무 패널이 있습니다. 그 트리 패널 안에는 xtype의 dockedItem이 있습니다 : 'textfield'. 이 텍스트 필드는 값을 가져 와서 specialkey 이벤트에 대한 핸들러 내에서 Ext.Ajax.Request를 통해 ajax 요청의 매개 변수로 사용합니다. 서버는 디코딩 된 응답의 JSON 객체를 반환하고 트리의 노드에 대한 폴더 ID를 포함합니다. SUCCESS에서 ajax 요청의 설정에는 getNodeById (IdFromAjaxResponse)를 통해 트리의 노드를 참조하고 확장해야하는 기능이 있습니다. 문제는 그 노드를 참조하는 방법을 모른다는 것입니다. 나는 this.getStore(). getNodeById를 시도했지만 'this'가 창을 참조한다. (나는 나무 패널에 대한 컨테이너라고 생각한다.) 트리 패널 또는 트리 스토어를 어떻게 참조합니까? 나는 도움 등

getCmp 같은 일부 코드를 직접 추천을 사용하지 않으 :

Ext.define('treePanel', { 
    extend: 'Ext.tree.Panel', 
    alias: 'widget.folderTreePanel', 
    //title: 'Folder Tree', 
    displayField: 'name', 
    rootVisible: false, 
    store: 'treeStore' 
    dockedItems: { 
     xtype: 'textfield', 
     name: 'Search', 
     allowBlank: true, 
     enableKeys: true, 
     listeners: { 
      specialkey: function (txtField, e) { //This handler will essentially take the search value and return the path from the DB 
       if (e.getKey() == e.ENTER){ 
        var searchValue = txtField.getValue(); 
        Ext.Ajax.request({ 
         url: 'MyServlet', 
         params: { 
          caseType: 'search', 
          value: searchValue 
         }, 
         success: function(response) { 
          response = Ext.decode(response.responseText); 
          var node, i=0; 
          expandFn = function() { 
This is where I have a problem->node = this.up('treePanel').getStore().getNodeById(response.IDs[i].folderId); 
           node.expand(); 
           i++; 
           if (i >= response.IDs.length-1) return; 
           expandFn(); 
          } 
         } 
        }); 
       } 
      }, scope: this 
     } 
    }, 
    columns: [{ 
     xtype: 'treecolumn', 
     text: 'Folder Name', 
     flex: 2, 
     sortable: true, 
     dataIndex: 'name' 
    },{ 
     text: 'Folder ID', 
     dataIndex: 'id', 
     flex: 2, 
     sortable: true 
    }] 
}); 

편집 : 나는 대답을 발견했다. 각 이벤트는이를 트리거 한 인스턴스를 인수로 처리기 함수에 전달합니다. 이 경우 txtField은 텍스트 필드 자체를 나타냅니다. 그런 다음 상속을 추적하여 패널을 찾을 수 있습니다.

그러나 지금 새로운 문제가 있습니다. expandFn()은 'ONCE'가 호출되고 'node'가 정의되지 않았기 때문에 중지됩니다. 응답 배열에 항목이 없어 질 때까지 반복됩니다. 다시 이것이 범위 문제라고 생각하지만, 나는 정말로 혼란스러워서 잘못되었다고 생각하지 않는다. ...

답변

0

이후 1 년이 넘었으며 extjs와 javascript 기초에 대해 훨씬 능숙 해졌습니다. 다음은 질문에 대답하기 위해 알아야 할 몇 가지 사항입니다.

this -> 자바 스크립트에서는 항상 우리가 사용하는 기능을 호출 한 객체를 참조합니다. 필자의 경우 함수가 ajax 요청의 success callback이므로 treepanel을 참조 할 수 없습니다. 이러한 문제를 해결하려면 함수 상단에서 액세스 할 수 있도록하려는 객체에 대한 참조를 설정하는 것이 좋습니다.제 경우에는 var treepanel = txtField.up('treePanel');을 사용하여 패널에 대한 참조를 얻을 수 있습니다.

expandFn -> 먼저 먼저 expandFn이 다른 함수 인 success 콜백 내에 정의되어 있습니다. 이로 인해 closure이 생성되고 싶지 않습니다. 클로저는 처리 할 준비가되지 않은 경우 문제를 일으킬 수있는 특수 기능을 제공합니다. expandFn을 가져와 treePanel의 범위에 외부에 정의하십시오. 여기서 가장 기본적인 문제는 node = this.up('treePanel')...this 키워드가 다시 한번 txtField을 언급하지 않는다고 생각했습니다. 이것이 treePanel 일찍 정의한 이유입니다. 우리는 그것을 통해 상점에 액세스 할 수 있습니다. 또한 node.expand()을 완료하는 데 시간이 걸립니다. 특히 노드가로드되지 않아 서버 요청을해야하는 경우가 있습니다. 이 경우를 들어 재귀을 할 수있는 올바른 방법 리스너를 추가하는 것입니다 :

node.on('expand', Ext.bind(treePanel.expandFn, treePanel, [args]), treePanel, {single:true})

여기서주의 할 몇 가지 : 우리가 expandFn 서로 다른 인수를 전달하려면

  • 우리는 Ext.bind를 사용해야은 기본적으로 expand 이벤트에 의해 전달 된 것보다 큽니다. 우리가 node.on('expand', treePanel.expandFn, treePanel, {single:true})을 작성한 다음 expand 이벤트가 발생하면 expandFn이 발생하지만 기본 인수는 문서에 따라 확장 된 노드와 eOpts 이벤트 옵션 객체입니다.
  • 을 추가하여 이벤트에서만 expandFn이 해고 될 것입니다. 우리는 노드를 확장 할 때마다 실행되는 것을 원하지 않습니다.
  • 우리가 node.expand()을 사용하기 전에이 수신기를 추가해야합니다.

이 답변은 위의 제공되는 코드에만 정확하게 적용될 수는 없지만 문제를 설명하고 문제를 해결하기 위해 무엇을해야하는지 설명합니다.

2

listeners config의 속성은 scope이다. 트리 패널에 설정할 수 있습니다.

[편집] 특수 키 수신기 내부에서 this을 변수로 지정하십시오. success 콜백 내에서 범위는 특수 키에 대한 수신기의 범위와 다릅니다. 아래의 수정 된 코드를 참조하십시오.

listeners: { 
    scope: this, 
    specialkey: function (txtField, e) { 
      var me = this; 
      if (e.getKey() == e.ENTER){ 
       var searchValue = txtField.getValue(); 
       Ext.Ajax.request({ 
        url: 'MyServlet', 
        params: { 
         caseType: 'search', 
         value: searchValue 
        }, 
        success: function(response) { 
         response = Ext.decode(response.responseText); 
         var node, i=0; 
         expandFn = function() { 
          node = me.getStore().getNodeById(response.IDs[i].folderId); 
          node.expand(); 
          i++; 
          if (i >= response.IDs.length-1) return; 
          expandFn(); 
         } 
        } 
       }); 
      } 
} 
+0

나는 이것을 시도했지만 어떤 이유로 작동하지 않았다 ... – Konstantine

0

문제는 나무 패널을 정의 할 때 당신의 범위 this는 현재 범위를 의미한다는 것이다. 이 트리 패널이 막 정의 될 때 범위를 트리 패널의 인스턴스로 설정할 수 없습니다.

이 문제를 해결하기 위해 당신은 당신의 나무 패널에 initComponent 기능을 추가하고 거기에 dockedItems의 설정을 설정할 수 있습니다

Ext.define('treePanel', { 
    extend: 'Ext.tree.Panel', 

    // [...] 

    initComponent: function() { 
     this.dockedItems = { 
      // [...] 
     }; 

     this.callParent(); 
    } 
}); 

의 차이는 initComponent에 의해 자동으로 호출하여 트리 패널의 멤버 함수라는 것이다 구성 요소의 인스턴스화 중 프레임 워크. 현재 텍스트 필드의 수신기 인 scope으로 사용할 수있는 인스턴스가 this입니다.

+0

나는 실제로 initComponent를 시도했지만 this.getDockedItems를 사용했고이 함수가 존재하지 않는다고 말했다 ... 즉, 이 '나무 패널을 언급하지 않았다 ?? – Konstantine

+0

당신은 그 기능을 호출 할 수 있어야하지만, 그 시점에서 컴포넌트가 완벽하게 준비되지 않았기 때문에 그렇게하지 말라고 권고하지 않습니다. 'Uncaught TypeError : 속성 'items'of undefined '을 읽을 수 없습니다. 그 이유는 도킹 된 항목 컬렉션이 아직 존재하지 않기 때문입니다. 예제에서 제안한 것처럼'this.dockedItems'을 대신 사용하십시오. – matt