發佈項目,加入CRUD功能

文章來源:http://blog.ddlisting.com/2016/04/16/fa-bu-xiang-mu-jia-ru-crudgong-neng/css

接着前面三篇:html

  1. 環境搭建以及使用Ember.js建立第一個靜態頁面
  2. 引入計算屬性、action、動態內容
  3. 模型,保存數據到數據庫

應用發佈

發佈方式一git

發佈的詳細教程請看guide on firebase。執行以下命令發佈項目。github

npm install -g firebase-tools
ember build --prod
firebase login
firebase init

執行命令過程須要輸入一個public的目錄,輸入dist後按enter。更新firebase.json的內容。web

{
  "firebase": "YOUR-APP-NAME",
  "public": "dist",
  "rewrites": [{
    "source": "**",
    "destination": "/index.html"
  }]
}

遺憾的是在我電腦上一直提示沒有firebase命令,即便我已經安裝了這個插件也不行。數據庫

發佈方式二npm

因爲上述方式沒法發佈想到到firebase,因此使用最原始的發佈方式,使用ember命令打包項目。而後本身把項目部署到服務器上。json

  1. 打包項目 打包項目使用命令ember build --prod,等到命令執行完畢後再項目的dist目錄下的全部文件即便打包後的項目文件。
  2. 複製打包後的文件到服務器上 獲得打包後的文件後能夠直接把這些文件複製到服務器上運行,好比複製到tomcat的webapps目錄下。
  3. 運行項目 複製到服務器以後啓動服務器,直接訪問:http://localhost:8080

增長刪除、修改功能

修改項目的library列表頁面,增長刪除和修改功能。bootstrap

<!-- app/templates/libraries/index.hbs -->
<h2>List</h2>
<div class="row">
  {{#each model as |library|}}
    <div class="col-md-4">
      <div class="panel panel-default library-item">
          <div class="panel-heading">
              <h3 class="panel-title">{{library.name}}</h3>
          </div>
          <div class="panel-body">
              <p>Address: {{library.address}}</p>
              <p>Phone: {{library.phone}}</p>
          </div>
          <div class="panel-footer text-right">
              {{#link-to 'libraries.edit' library.id class='btn btn-success btn-xs'}}Edit{{/link-to}}
              <button class="btn btn-danger btn-xs" {{action 'deleteLibrary' library}}>Delete</button>
          </div>
      </div>
    </div>
  {{/each}}
</div>

相比原來的代碼增長了一個鏈接和一個按鈕,分別用於編輯和刪除library信息。相對於須要增長一個路由libraries/edit和一個處理的動做{{action 'deleteLibrary'}}。 若是此時運行http://localhost:4200/libraries會出現錯誤,由於還沒定義路由libraries/editaction。別急,先一步步來,下面先增長一些css樣式。ubuntu

# app/styles/app.scss
@import 'bootstrap';

body {
  padding-top: 20px;
}

html {
  overflow-y: scroll;
}

.library-item {
  min-height: 150px;
}

建立路由libraries/edit和路由對應的模板

簡單起見直接使用Ember CLI命令建立,就不手動建立了。執行命令:ember g route libraries/edit建立路由和路由對應的模板。 建立完成以後還須要手動修改app/router.js文件,內容以下:

// app/router.js

import Ember from 'ember';
import config from './config/environment';

var Router = Ember.Router.extend({
  location: config.locationType
});

Router.map(function() {

  this.route('about');
  this.route('contact');

  this.route('admin', function() {
    this.route('invitation');
    this.route('contact');
  });

  this.route('libraries', function() {
    this.route('new');
    // :library_id是一個動態段,會根據實際的URL變化
    this.route('edit', { path: '/:library_id/edit' });
  });
});

export default Router;

注意this.route('edit', { path: '/:library_id/edit' });這行代碼的設置。與普通的路由稍有不一樣這裏增長了一個參數,而且參數內使用path設定路由渲染以後edit會被/:library_id/edit替換。 編譯、渲染以後的URL格式爲http://example.com/libraries/1234/edit其中:library_id這是一個動態段,這個URL例子中動態段library_id的值就是1234,而且能夠在路由類中獲取這個動態段的值。 更多有關動態段的介紹請看Ember.js 入門指南之十三{{link-to}} 助手或者Dynamic Segments

配置完路由以後修改路由libraries/edit.js的代碼。

// app/routes/libraries/edit.js
import Ember from 'ember';

export default Ember.Route.extend({

  model(params) {
    // 獲取動態段library_id的值 
    return this.store.findRecord('library', params.library_id);
  },

  actions: {

    saveLibrary(newLibrary) {
      newLibrary.save().then(() => this.transitionTo('libraries'));
    },

    willTransition(transition) {

      let model = this.controller.get('model');

      if (model.get('hasDirtyAttributes')) {
        let confirmation = confirm("Your changes haven't saved yet. Would you like to leave this form?");

        if (confirmation) {
          model.rollbackAttributes();
        } else {
          transition.abort();
        }
      }
    }
  }
});

代碼this.store.findRecord('library', params.library_id);的意思是根據模型的id屬性值查詢某個記錄,其中library_id就是動態段的值,這個值是Ember解析URL獲得的。正如前面所說:http://example.com/libraries/1234/edit這個URL動態段的值就是1234。 Ember會自動根據URL的格式解析獲得。而且能夠在路由類中獲取。默認狀況下動態段的值是數據的id值。代碼中的另外兩個方法saveLibrary()willTransition()在前一篇文章模型,保存數據到數據庫已經介紹過,在此再也不贅述。 方法willTransition()的做用就是:當用戶修改了數據以後沒有點擊保存就離開頁面時會提示用戶是否確認不保存就離開頁面!經過控制器中的屬性hasDirtyAttributes判斷頁面的值是否發生了變化。方法rollbackAttributes()會重置model中的值。方法abourt()能夠阻止路由的跳轉,有關路由的跳轉請看Ember.js 入門指南之二十四終止與重試路由跳轉。從new.hbs複製代碼到edit.hbs,而後在稍加修改。

<!-- app/templates/libraries/edit.hbs -->

<h2>Edit Library</h2>

<div class="form-horizontal">
    <div class="form-group">
        <label class="col-sm-2 control-label">Name</label>
        <div class="col-sm-10">
          {{input type="text" value=model.name class="form-control" placeholder="The name of the Library"}}
        </div>
    </div>
    <div class="form-group">
        <label class="col-sm-2 control-label">Address</label>
        <div class="col-sm-10">
          {{input type="text" value=model.address class="form-control" placeholder="The address of the Library"}}
        </div>
    </div>
    <div class="form-group">
        <label class="col-sm-2 control-label">Phone</label>
        <div class="col-sm-10">
          {{input type="text" value=model.phone class="form-control" placeholder="The phone number of the Library"}}
        </div>
    </div>
    <div class="form-group">
        <div class="col-sm-offset-2 col-sm-10">
            <button type="submit" class="btn btn-default" {{action 'saveLibrary' model}}>Save changes</button>
        </div>
    </div>
</div>

等待項目重啓完成,進入到修改界面,任意修改界面上的數據,不點擊保存而後任意點擊其餘連接會彈出提示,詢問你是否確認離開頁面。操做步驟以下截圖。

library主頁

library修改頁面

注意:看瀏覽器的URL。首頁模板代碼{{#link-to 'libraries.edit' library.id class='btn btn-success btn-xs'}}Edit{{/link-to}}中的路由libraries.edit渲染以後會獲得形如libraries/xxx/edit的URL,其中xxx就是動態段的值。

修改name的值,而後點擊菜單的Home

library未保存離開頁面提示

彈出提示信息。若是點擊取消會停留在當前頁面,若是選中肯定會跳轉到首頁(由於我點擊的是菜單的Home)。

修改後點擊保存

成功保存了修改的內容。到此實現了修改功能。

實現刪除功能

刪除功能比修改更加簡單,直接在方法deleteLibrary里根據id屬性值刪除數據便可。id屬性值已經在模板頁面做爲參數傳遞到方法中。直接獲取便可。

// app/routes/libraries/index.js

import Ember from 'ember';

export default Ember.Route.extend({
  model() {
    return this.store.findAll('library');
  },
  actions: {
      // 刪除一個library記錄
      deleteLibrary(library) {  //參數library已經在模板中傳遞過來
      let confirmation = confirm('Are you sure?');

      if (confirmation) {
        library.destroyRecord();
      }
    }
  }
});

模板中是這樣調用刪除方法的<button class="btn btn-danger btn-xs" {{action 'deleteLibrary' library}}>Delete</button>,看到參數library了吧,這個參數就是一個library模型對象。 能夠直接調用方法destroyRecord()實現刪除數據。

點擊刪除按鈕

選中肯定以後刪除就會馬上刪除,列表上的數據也會動態更新。

家庭做業

參照library的功能實現contact的刪除與修改。

新建路由和模板

ember g route admin/contact/edit
ember g template admin/contact/index

修改router.js,增長配置

// app/router.js

this.route('admin', function() {
  this.route('invitation');
  this.route('contact', function() {
    this.route('edit', { path: '/:contact_id/edit' });
  });
});

省略其餘內容,僅僅列出修改部分。

複製admin/contact.hbs的內容到admin/contact/index.hbs,而後空admin/contact.hbs再在文件內添加{{outlet}}

admin/contact.hbs

<!-- app/templates/admin/contact.hbs -->
{{outlet}}

admin/contact/index.hbs

{{! app/templates/admin/contact/index.hbs}}

<h1>Contacts</h1>

<table class="table table-bordered table-striped">
    <thead>
      <tr>
          <th>ID</th>
          <th>E-mail</th>
          <th>Message</th>
          <th>Operation</th>
      </tr>
    </thead>
    <tbody>
    {{#each model as |contact|}}
        <tr>
            <th>{{contact.id}}</th>
            <td>{{contact.email}}</td>
            <td>{{contact.message}}</td>
            <td>
                {{#link-to 'admin.contact.edit' contact.id class='btn btn-success btn-xs'}}Edit{{/link-to}}
                <button class="btn btn-danger btn-xs" {{action 'deleteContact' contact}}>Delete</button>
            </td>
        </tr>
    {{/each}}

    </tbody>
</table>

增長刪除、修改按鈕。

複製app/templates/contact.hbsadmin/contact/edit.hbs並作修改

admin/contact/edit.hbs

{{! app/templates/admin/contact/edit.hbs}}

<div class="col-md-6 col-xs-6">
   <form>
     <div class="form-group">
         <label for="exampleInputEmail1">Email address</label>
         {{input type="email" value=model.email class="form-control col-sm-6 col--6" placeholder="Please type your e-mail address." autofocus="autofocus"}}
     </div>
     <div class="form-group">
         <label for="exampleInputPassword1">Your message</label>
         {{textarea class="form-control" placeholder="Your message. (At least 5 characters.)" rows="7" value=model.message}}
     </div>

     <button class="btn btn-primary" disabled={{model.isDisabled}} {{action 'saveContact' model}}>Save</button>
     {{#link-to 'admin.contact' class="btn btn-default"}}Return{{/link-to}}
   </form>
</div>

修改routes/context.js

// app/routes/contact.js

import Ember from 'ember';

export default Ember.Route.extend({
    model: function() {
        return this.store.findAll('contact');
    },
    actions: {
        deleteContact: function(contact) {
            let confirmation = confirm('Are you sure?');

            if (confirmation) {
              contact.destroyRecord();
            }
        }
    }
});

修改app/routes/admin/contact/edit.js

// app/routes/admin/contact/edit.js

import Ember from 'ember';

export default Ember.Route.extend({

  model(params) {
    // 獲取動態段library_id的值
    return this.store.findRecord('contact', params.contact_id);
  },

  actions: {

    saveContact(newContact) {
      newContact.save().then(() => this.transitionTo('admin.contact'));
    },

    willTransition(transition) {

      let model = this.controller.get('model');

      if (model.get('hasDirtyAttributes')) {
        let confirmation = confirm("Your changes haven't saved yet. Would you like to leave this form?");

        if (confirmation) {
          model.rollbackAttributes();
        } else {
          transition.abort();
        }
      }
    }
  }
});

運行結果再也不截圖列出,請讀者自行試驗。

<br> 爲了照顧懶人我把完整的代碼放在[GitHub](https://github.com/ubuntuvim/library-app)上,能夠拿來作參照。博文通過屢次修改,博文上的代碼與github代碼可能有出入,不過影響不大!若是你以爲博文對你有點用,請在github項目上給我點個`star`吧。您的確定對我來講是最大的動力!!

相關文章
相關標籤/搜索