2012-09-22 37 views
1

我有一个简单的登录表单,在正确登录后滑入下一个视图。我找到了两个例子的组合。我想使用MVC模式将这个登录分成几个文件。在网上看到的很多例子中,这是Sencha Touch 2中的一块蛋糕。无论我尝试什么,我都无法使它工作。我习惯用Flex,Java,ActionScript,Php编程,但Sencha jSon是另外一种球类游戏。任何人都可以帮助我呢?我想有一个模型,商店,视图和控制器封装在推荐的文件夹结构:如何在Sencha Touch 2中使用简单的app.js创建MVC

-app 
    -controller 
    -Controller.js 
    -model 
    -Model.js 
    -store 
    -Store.js 
    -view 
    -Main.js 
    -Login.js 
    -SecondView.js 
-app.js 
-app.css 
-index.html 

这是包含在一个文件中的所有逻辑当前app.js。

Ext.require([ 
'Ext.form.Panel', 
'Ext.form.FieldSet', 
'Ext.field.Text', 
'Ext.field.Password', 

'Ext.data.Store' 
]); 

Ext.define('User', { 
extend: 'Ext.data.Model', 

config: { 
    fields: [ 
     {name: 'name', type: 'string'}, 
     {name: 'password', type: 'string'} 
    ] 
} 
}); 

Ext.setup({ 
icon: 'icon.png', 
tabletStartupScreen: 'tablet_startup.png', 
phoneStartupScreen: 'phone_startup.png', 
glossOnIcon: false, 
onReady: function() { 
    var form; 

    var formBase = { 
     url: 'login.php', 
     standardSubmit: false, 
     title:"Login", 
     items: [ 
      { 
       xtype: 'fieldset', 
       title: 'MyCompony', 
       instructions: 'Log in with username and password.', 
       defaults: { 
        required: true, 
        labelAlign: 'left', 
        labelWidth: '40%' 
       }, 
       items: [ 
        { 
         xtype: 'textfield', 
         name: 'name', 
         label: 'Name', 
         value: 'user', 
         autoCapitalize: false 
        }, 
        { 
         xtype: 'passwordfield', 
         name: 'password', 
         label: 'Password', 
         value: 'test' 
        } 
       ] 
      }, 
      { 
       xtype: 'toolbar', 
       docked: 'bottom', 
       items: [ 
        {xtype: 'spacer'}, 
        { 
         text: 'Reset', 
         handler: function() { 
          form.reset(); 
         } 
        }, 
        { 
         text: 'Login', 
         ui: 'confirm', 
         handler: function() { 
          if (formBase.user) { 
           form.updateRecord(formBase.user, true); 
          } 
          form.submit({ 
           waitMsg: {message: 'Submitting'} 
          }); 
         } 
        } 
       ] 
      } 
     ], 

     listeners: { 
      submit: function(form, result) { 
       console.log('success', Ext.toArray(arguments)); 
       view.push({ 
        title: 'Second View', 
        padding: 10, 
        items: [ 
         { 
          html: 'Second view' 
         }, 
         { 
          xtype: 'button', 
          text: 'Pop this view!', 
          width: 200, 
          handler: function() { 
           view.pop(); 
          } 
         } 
        ] 
       }); 
      }, 
      exception: function(form, result) { 
       console.log('failure', Ext.toArray(arguments)); 
      } 
     } 
    }; 

    if (Ext.os.deviceType == 'Phone') { 
     Ext.apply(formBase, { 
      xtype: 'formpanel', 
      autoRender: true 
     }); 
    } else { 
     Ext.apply(formBase, { 
      xtype: 'formpanel', 
      autoRender: true, 
      padding: 100 
     }); 
    } 
    form = Ext.create('Ext.form.Panel', formBase); 
    var view = Ext.create('Ext.navigation.View', { 
     fullscreen: true, 
     items: [ 
      form 
     ] 
    }); 

} 
}); 

这是一个简单的php脚本(login.php)来回答登录请求。

<?php 
$pw = $_REQUEST['password']; 
header('Content-Type: application/json'); 
if($pw == 'asdf'){ 
    echo '{"success":true, "msg":'.json_encode('This User is authorized').'}'; 
}else{ 
    echo '{"success":false, "msg":'. 
     json_encode('This User is NOT authorized'). 
     ', "errors" : { "password" :'.json_encode('Password is required'). 
     '}'. 
     ', "pwd" :'.json_encode($pw).'}'; 
} 

有人吗?

回答

5

经过一番研究(天)好了,这里的答案:

的index.html:

<!DOCTYPE html> 
<html> 
<head> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
    <title>Map</title> 
    <link rel="stylesheet" href="../../resources/css/sencha-touch.css" type="text/css"> 
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script> 
    <script type="text/javascript" src="../../builds/sencha-touch-all-debug.js"></script> 
    <script type="text/javascript" src="app.js"></script> 
</head> 
<body> 
</body> 
</html> 

的login.php:

<?php 
$pw = $_REQUEST['password']; 
header('Content-Type: application/json'); 
if($pw == 'test'){ 
    echo '{"success":true, "msg":'.json_encode('This User is authorized').'}'; 
}else{ 
    echo '{"success":false, "msg":'. 
     json_encode('This User is NOT authorized'). 
     ', "errors" : { "password" :'.json_encode('Password is required'). 
     '}'. 
     ', "pwd" :'.json_encode($pw).'}'; 
} 
?> 

app.js:

Ext.Loader.setConfig({ enabled: true }); 
Ext.application({ 
    name: 'AddressBook', 

    icon: 'resources/images/icon.png', 
    tabletStartupScreen: 'resources/images/tablet_startup.png', 
    phoneStartupScreen: 'resources/images/phone_startup.png', 
    glossOnIcon: true, 

    models: ['WorkOrder'], 
    stores: ['WorkOrders'], 
    views: ['Main','workorder.Map'], 
    controllers: ['AppController'], 

    launch: function() { 
     Ext.Viewport.add({ 
      xclass: 'AddressBook.view.Main' 
     }); 
    } 
}); 

werkorders.json

[ 
    { 
     "id": "14", 
     "lastName": "Franklin", 
     "latitude": "52.370216", 
     "longitude": "4.895168" 
    }, 
    { 
     "id": "2", 
     "lastName": "Johnson", 
     "latitude": "52.370316", 
     "longitude": "4.895868" 
    }, 
    { 
     "id": "8", 
     "lastName": "Vanderburg", 
     "latitude": "52.370516", 
     "longitude": "4.895968" 
    } 
] 

应用程序/视图/ Main.js:

Ext.define('AddressBook.view.Main', { 
    extend: 'Ext.navigation.View', 
    xtype: 'mainview', 

    requires: [ 
     'AddressBook.view.Login', 
     'AddressBook.view.workorder.Map', 
     'AddressBook.view.workorder.Edit' 
    ], 

    config: { 
     autoDestroy: false, 

     navigationBar: { 
      ui: 'sencha', 
      items: [ 
       { 
        xtype: 'button', 
        id: 'editButton', 
        text: 'Edit', 
        align: 'right', 
        hidden: true, 
        hideAnimation: Ext.os.is.Android ? false : { 
         type: 'fadeOut', 
         duration: 200 
        }, 
        showAnimation: Ext.os.is.Android ? false : { 
         type: 'fadeIn', 
         duration: 200 
        } 
       }, 
       { 
        xtype: 'button', 
        id: 'saveButton', 
        text: 'Save', 
        ui: 'sencha', 
        align: 'right', 
        hidden: true, 
        hideAnimation: Ext.os.is.Android ? false : { 
         type: 'fadeOut', 
         duration: 200 
        }, 
        showAnimation: Ext.os.is.Android ? false : { 
         type: 'fadeIn', 
         duration: 200 
        } 
       } 
      ] 
     }, 

     items: [ 
      { xtype: 'loginForm' } 
     ] 
    } 
}); 

应用程序/视图/ Login.js:

Ext.define('AddressBook.view.Login', { 
    title: "Luminizer Login", 
    extend: 'Ext.form.Panel', 
    xtype: 'loginForm', 

    config: { 
     url: 'login.php', 
     standardSubmit: false, 
     title: 'Login Luminizer', 
     layout: 'vbox', 
     items: [ 
      { 
       xtype: 'fieldset', 
       title: 'MyCompony', 
       instructions: 'Log in with username and password.', 
       defaults: { 
        required: true, 
        labelAlign: 'left', 
        labelWidth: '40%' 
       }, 
       items: [ 
        { 
         xtype: 'textfield', 
         name: 'username', 
         id: 'username', 
         label: 'Name', 
         value: 'user', 
         autoCapitalize: false 
        }, 
        { 
         xtype: 'passwordfield', 
         name: 'password', 
         id: 'password', 
         label: 'Password', 
         value: 'test' 
        } 
       ] 
      }, 
      { 
       xtype: 'toolbar', 
       docked: 'bottom', 
       items: [ 
        {xtype: 'spacer'}, 
        { 
         text: 'Reset', 
         handler: function() { 
          var form = this.parent.parent; 
          form.reset(); 
         } 
        }, 
        { 
         text: 'Login', 
         ui: 'confirm', 
         handler: function() { 
          var form = this.parent.parent; 

          var username = form.getValues().username;//form.down('#username').getValue(); 
          var password = form.getValues().password;//down('#password').getValue(); 
          form.fireEvent('login', username, password); 
         } 
        } 
       ] 
      } 
     ] 
    }, 

    resetForm: function() { 
     var view = this.parent; 
     view.down("#username").setValue(""); 
     view.down("#password").setValue(""); 
    } 
}); 

应用程序/视图/工作单/ map.js:

Ext.define('AddressBook.view.workorder.Map', { 
    extend: 'Ext.Panel', 
    xtype: 'map-show', 
    requires: [ 
     'Ext.Map' 
    ], 
    config: { 
     title: 'Information', 
     layout: 'card', 
     items: [ 
      { 
       xtype: 'map', 
       mapOptions : { 
        zoom : 15, 
        mapTypeId : google.maps.MapTypeId.ROADMAP, 
        navigationControl: true, 
        navigationControlOptions: { 
         style: google.maps.NavigationControlStyle.DEFAULT 
        } 
       } 
      } 
     ] 
    }, 

    centerMap: function(newRecord) { 
     if (newRecord) { 
      this.down('map').setMapCenter({ 
       latitude: newRecord.data.latitude, 
       longitude: newRecord.data.longitude 
      }); 
     } 
    }, 

    setMarkers: function(markers) { 
     var mapPanel = this; 
     var map = this.down("map")._map; 
     mapPanel.markerDataDict = {}; 
     mapPanel.markerDict = {}; 


     if(!mapPanel.infowindow) { 
      mapPanel.infowindow = new google.maps.InfoWindow({ 
       content: 'Sencha HQ' 
      }); 
     } 
     for(var i = 0 ;i < markers.length; i++) { 
      var markerData = markers[i]; 
      map.setZoom(15); 
      var latitude = Number(markerData.data.latitude); 
      var longitude = Number(markerData.data.longitude); 
      var position = new google.maps.LatLng(latitude, longitude); 
      mapPanel.markerDataDict[position] = markerData; 
      var marker = new google.maps.Marker({ 
       position: position, 
       title : markerData.data.id, 
       map: map 
      }); 
      mapPanel.markerDict[position] = marker; 

      google.maps.event.addListener(marker, 'click', function(mouseEvent) { 
       var lat = Math.round(mouseEvent.latLng.lat() * 1000000)/1000000; 
       var lng = Math.round(mouseEvent.latLng.lng() * 1000000)/1000000; 
       var id = mapPanel.markerDataDict[mouseEvent.latLng].data.id; 
       mapPanel.infowindow = new google.maps.InfoWindow(); 
       mapPanel.infowindow.setContent(['Werkorder: '+ id +'<br/>', 
               'lat.:' + lat + '<br/>', 
               'long.:' + lng ].join("")); 
       if(mapPanel.oldInfowindow) 
        mapPanel.oldInfowindow.close(); 
       mapPanel.oldInfowindow = mapPanel.infowindow; 
       mapPanel.infowindow.open(map, mapPanel.markerDict[mouseEvent.latLng]); 
       mapPanel.infowindow.setPosition(mouseEvent.latLng); 
       mapPanel.fireEvent('markerClicked', mapPanel.markerDataDict[mouseEvent.latLng]) 
      }); 
     } 
    } 
}); 

app/view/workorder/Edit。JS:

Ext.define('AddressBook.view.workorder.Edit', { 
    extend: 'Ext.Container', 
    xtype: 'contact-edit', 

    config: { 
     title: 'Edit', 
     layout: 'fit', 

     items: [ 
      { 
       xtype: 'formpanel', 
       items: [ 
        { 
         xtype: 'fieldset', 
         defaults: { 
          labelWidth: '35%' 
         }, 
         title: 'Information', 
         items: [ 
          { 
           xtype: 'textfield', 
           label: 'First Name', 
           name: 'firstName' 
          }, 
          { 
           xtype: 'textfield', 
           label: 'Last Name', 
           name: 'lastName' 
          }, 
          { 
           xtype: 'textfield', 
           label: 'Title', 
           name: 'title' 
          } 
         ] 
        }, 
        { 
         xtype: 'fieldset', 
         defaults: { 
          labelWidth: '35%' 
         }, 
         title: 'Contact Information', 
         items: [ 
          { 
           xtype: 'textfield', 
           label: 'Telephone', 
           name: 'telephone' 
          } 
         ] 
        }, 
        { 
         xtype: 'fieldset', 
         title: 'Address', 
         defaults: { 
          labelWidth: '35%' 
         }, 
         items: [ 
          { 
           xtype: 'textfield', 
           label: 'City', 
           name: 'city' 
          }, 
          { 
           xtype: 'textfield', 
           label: 'State', 
           name: 'state' 
          }, 
          { 
           xtype: 'textfield', 
           label: 'Country', 
           name: 'country' 
          } 
         ] 
        } 
       ] 
      } 
     ], 

     listeners: { 
      delegate: 'textfield', 
      keyup: 'onKeyUp' 
     }, 

     record: null 
    }, 

    updateRecord: function(newRecord) { 
     this.down('formpanel').setRecord(newRecord); 
    }, 

    saveRecord: function() { 
     var formPanel = this.down('formpanel'), 
      record = formPanel.getRecord(); 

     formPanel.updateRecord(record); 

     return record; 
    }, 

    onKeyUp: function() { 
     this.fireEvent('change', this); 
    } 
}); 

应用程序/控制器/ AppController.js:

Ext.define('AddressBook.controller.AppController', { 
    extend: 'Ext.app.Controller', 

    config: { 
     refs: { 
      main: 'mainview', 
      editButton: '#editButton', 
      contacts: 'contacts', 
      loginForm: 'loginForm', 
      showMap: 'map-show', 
      editContact: 'contact-edit', 
      saveButton: '#saveButton' 
     }, 

     control: { 
      main: { 
       push: 'onMainPush', 
       pop: 'onMainPop' 
      }, 
      editButton: { 
       tap: 'onContactEdit' 
      }, 
      contacts: { 
       itemtap: 'onMarkerSelect' 
      }, 
      loginForm: { 
       login: 'onLogin' 
      }, 
      showMap: { 
       markerClicked: 'onMarkerSelect' 
      }, 
      saveButton: { 
       tap: 'onContactSave' 
      }, 
      editContact: { 
       change: 'onContactChange' 
      } 
     } 
    }, 

    onMainPush: function(view, item) { 
     var editButton = this.getEditButton(); 

     if (item.xtype == "map-show") { 
      this.getLoginForm().reset(); 

      this.showEditButton(); 
     } else { 
      this.hideEditButton(); 
     } 
    }, 

    onMainPop: function(view, item) { 
     if (item.xtype == "contact-edit") { 
      this.showEditButton(); 
     } else { 
      this.hideEditButton(); 
     } 
    }, 

    onMarkerSelect: function(record) { 
     var editButton = this.getEditButton(); 

     if (!this.showEdit) { 
      this.showEdit = Ext.create('AddressBook.view.workorder.Edit'); 
     } 

     // Bind the record onto the show contact view 
     this.showEdit.setRecord(record); 

     // Push the show contact view into the navigation view 
     this.getMain().push(this.showEdit); 
    }, 

    onLogin: function(username, password) { 
     var controller = this; 
     Ext.Ajax.request({ 
      url: 'login.php', 
      method: 'POST', 
      disableCaching: true, 

      params: { 
       username: username, 
       password: password 
      }, 

      success: function(response) { 
       console.log("Login successful for {username}"); 
       var editButton = controller.getEditButton(); 
       if (!controller.showContact) { 
        controller.showContact = Ext.create('AddressBook.view.workorder.Map'); 
       } 

       var store = Ext.getStore("WorkOrders"); 
       store.load({callback: function(records, operation, success) { 
           if(success) { 
            console.log(records); 
            controller.showContact.centerMap(store.data.items[0]); 
            controller.showContact.setMarkers(store.data.items); 
            // Push the show contact view into the navigation view 
            controller.getMain().push(controller.showContact); 
            controller.getLoginForm().resetForm(); 
           } 
          }, 
          scope: this 
       }); 

      }, 

      failure: function(response) { 
       console.log("Login failure for {username}"); 
      } 
     }); 

    }, 

    onMarkerClicked: function(markerData) { 

    }, 

    onContactEdit: function() { 
     if (!this.editContact) { 
      this.editContact = Ext.create('AddressBook.view.workorder.Edit'); 
     } 

     // Bind the record onto the edit contact view 
     this.editContact.setRecord(this.getShowContact().getRecord()); 

     this.getMain().push(this.editContact); 
    }, 

    onContactChange: function() { 
     this.showSaveButton(); 
    }, 

    onContactSave: function() { 
     var record = this.getEditContact().saveRecord(); 

     this.getShowContact().updateRecord(record); 

     this.getMain().pop(); 
    }, 

    showEditButton: function() { 
     var editButton = this.getEditButton(); 

     if (!editButton.isHidden()) { 
      return; 
     } 

     this.hideSaveButton(); 

     editButton.show(); 
    }, 

    hideEditButton: function() { 
     var editButton = this.getEditButton(); 

     if (editButton.isHidden()) { 
      return; 
     } 

     editButton.hide(); 
    }, 

    showSaveButton: function() { 
     var saveButton = this.getSaveButton(); 

     if (!saveButton.isHidden()) { 
      return; 
     } 

     saveButton.show(); 
    }, 

    hideSaveButton: function() { 
     var saveButton = this.getSaveButton(); 

     if (saveButton.isHidden()) { 
      return; 
     } 

     saveButton.hide(); 
    } 
}); 

应用程序/模型/ WorkOrder.js:

Ext.define('AddressBook.model.WorkOrder', { 
    extend: 'Ext.data.Model', 

    config: { 
     fields: [ 
      'id', 
      'lastName', 
      'latitude', 
      'longitude' 
     ] 
    } 
}); 

应用程序/商店/ WorkOrders.js:

Ext.define('AddressBook.store.WorkOrders', { 
    extend: 'Ext.data.Store', 

    config: { 
     model: 'AddressBook.model.WorkOrder', 
     autoLoad: false, 
     sorters: 'id', 
     proxy: { 
      type: 'ajax', 
      url: 'werkorders.json', 
      reader: { 
       type: 'json' 
      } 
     } 
    } 
}); 
+0

感谢您的这项工作!它为我节省了一些时间。这里有几个你在这里工作的7z文件。我添加了touch .js和.css文件并进行了测试! unix line-endings https://onedrive.live.com/redir?resid=EAF1A9897959A658!67874&authkey=!AN5FGmwv9U6-PK8&ithint=file%2c7z。 windows line-endings https://onedrive.live.com/redir?resid=EAF1A9897959A658!67873&authkey=!AIIDGSbdpJPO5ck&ithint=file%2c7z – wasatchwizard

1

我强烈建议您观看此视频,大约已了解MVC应用程序在煎茶触摸2

Here is the link

此影片的,你可以申请你的情况的处理方式为例。

+0

是的,我知道这个伟大的视频,并研究了这个例子。这很清楚。但最后我无法将其整合到我的代码中。我的问题仍然是如何在单独的视图中将它与导航选项卡视图组合在一起。以及如何获取Controller中的[Login]按钮的处理程序,并让此Controller通知它已成功记录,以便视图堆栈可以推送新视图。 –

-1

MVC的重点是打破逻辑。我不能说在问题中保留app.js中的所有逻辑有什么问题。但看了各种例子后,我了解到app.js是一个简短的文件,不是一个大文件。将逻辑部分移动到各种其他文件(控制器逻辑到controller.js和全部),然后再试一次。
一个例子我能很快指出的是,下面的代码

var formBase = { 
    url: 'login.php', 
    standardSubmit: false, 
    title:"Login", 
    items: [ 
     { 
      xtype: 'fieldset', 
      title: 'MyCompony', 
      instructions: 'Log in with username and password.', 
      defaults: { 
       ... 
      }, 
      items: [ 
       { 
        xtype: 'textfield', 
        ... 
       }, 
       { 
        xtype: 'passwordfield', 
        ... 
       } 
      ] 
     }, 
     { 
      xtype: 'toolbar', 
      ... 
      items: [ 
       {xtype: 'spacer'}, 
       { 
        ... 
       }, 
       { 
        text: 'Login', 
        ... 
        handler: function() { 
         ... 
        } 
       } 
      ] 
     } 
    ], 

应该是在view.js. 这就是MVC的含义。希望它能回答你的问题。

+0

是的,谢谢你,但不,它没有回答我的问题。顺便说一下,你在这里指出的代码不会是我的View.js,因为它也包含Controller部分。我知道MVC的优点。这就是为什么我会努力获得答案。保持app.js中的所有逻辑会使我疯狂。对我来说,最大的好处是所有的数据都存储在一个地方(模型),它可以让你在整个应用程序中保持一致。其次,我会说,能够重用代码并摆脱冗余(控制器)使其不易出错,第三,它有助于在团队中工作。 –

相关问题