文档章节

发布项目,加入CRUD功能

ubuntuvim
 ubuntuvim
发布于 2016/04/16 17:05
字数 2280
阅读 163
收藏 4

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

接着前面三篇:

  1. 环境搭建以及使用Ember.js创建第一个静态页面
  2. 引入计算属性、action、动态内容
  3. 模型,保存数据到数据库

应用发布

发布方式一

发布的详细教程请看guide on firebase。执行如下命令发布项目。

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

执行命令过程需要输入一个public的目录,输入dist后按enter。更新firebase.json的内容。

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

遗憾的是在我电脑上一直提示没有firebase命令,即使我已经安装了这个插件也不行。

发布方式二

由于上述方式无法发布想到到firebase,所以使用最原始的发布方式,使用ember命令打包项目。然后自己把项目部署到服务器上。

  1. 打包项目 打包项目使用命令ember build --prod,等到命令执行完毕后再项目的dist目录下的所有文件即使打包后的项目文件。
  2. 复制打包后的文件到服务器上 得到打包后的文件后可以直接把这些文件复制到服务器上运行,比如复制到tomcat的webapps目录下。
  3. 运行项目 复制到服务器之后启动服务器,直接访问:http://localhost:8080

增加删除、修改功能

修改项目的library列表页面,增加删除和修改功能。

<!-- 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样式。

# 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`吧。您的肯定对我来说是最大的动力!!

© 著作权归作者所有

ubuntuvim
粉丝 33
博文 76
码字总数 98477
作品 1
深圳
后端工程师
私信 提问
加载中

评论(4)

山水人家

引用来自“山水人家”的评论

你好,我使用第二种方法,打包,发布之前的项目,放到tomcat中什么都不显示,是不是那个地方有问题。

引用来自“ubuntuvim”的评论

由于回复不支持图片也不知道代码输入,我做了个简单说明,说明网址:https://github.com/ubuntuvim/study-note/blob/master/%E5%85%B6%E4%BB%96%E7%AC%94%E8%AE%B0/%E9%83%A8%E7%BD%B2Ember%E9%A1%B9%E7%9B%AE%E5%88%B0Tomcat.md
谢谢
ubuntuvim
ubuntuvim 博主

引用来自“山水人家”的评论

你好,我使用第二种方法,打包,发布之前的项目,放到tomcat中什么都不显示,是不是那个地方有问题。
由于回复不支持图片也不知道代码输入,我做了个简单说明,说明网址:https://github.com/ubuntuvim/study-note/blob/master/%E5%85%B6%E4%BB%96%E7%AC%94%E8%AE%B0/%E9%83%A8%E7%BD%B2Ember%E9%A1%B9%E7%9B%AE%E5%88%B0Tomcat.md
ubuntuvim
ubuntuvim 博主

引用来自“山水人家”的评论

你好,我使用第二种方法,打包,发布之前的项目,放到tomcat中什么都不显示,是不是那个地方有问题。
是执行ember build --prod打包后的的文件吧?然后放在tomcat的webapps\ROOT目录下。 原来ROOT的内容可以全部删除。我的是可以正常运行,不知道你的是不是这样做到! 如果还是不行请配置 tomcat/conf/server.xml文件。在最后的Host标签内增加 如下行的配置 ”“ 其中C:\Users\Administrator\Desktop\web是你打包后项目所在路径。
山水人家
你好,我使用第二种方法,打包,发布之前的项目,放到tomcat中什么都不显示,是不是那个地方有问题。
ThinkphpHelper 0.33 发布,Thinkphp 生成工具

ThinkphpHelper 升级至 0.33 加入了生成关联模型和视图模型的功能 修正了读取带下划线数据表时生成代码不正确的BUG 顺带修正了一些其他小bug 项目地址:https://github.com/zhuanqianfish/Th...

Superman371
2014/10/14
4.8K
7
Fly的狐狸/jmoney

财务管理jfinal+beetl 本网站后台基于Jfinal开发,前台模板使用beetl,数据库为Mysql。 演示地址:http://www.jflyfox.com/jmoney 平台部署说明 下载jmoney项目:配置数据库文件/jmoney/src...

Fly的狐狸
2014/06/05
0
0
Avue 是一个后台集成解决方案支持SSR(服务端渲染)和SPA(单例页面),

https://gitee.com/smallweigit/avue.git vue只是刚起步,很多功能还在开发中敬请期待...... 简体中文 欢迎加入QQ交流群,互相学习 一键加群: 简介 是一个后台集成解决方案支持SSR(服务端渲...

Smallwei小伟
2018/02/08
1K
0
Kamike.divide 0.1 发布,分库分表Sharding中间件

大年初五,在单位24小时值班,重新捡起来kamike.divide中间件的编写 经过5个小时左右的开发和整理工作,到23点36分。计划工作全部完成。。 个人认为Kamike.divide可以作为一个可用版本进行发...

Brin想写程序
2014/02/04
754
1
Mybatis 增强类库 - easymybatis

easymybatis是一个mybatis增强类库,目的为简化mybatis的开发,让开发更高效。 easymybatis的特性如下: 无需编写xml文件即可完成CRUD操作。 支持多表查询、聚合查询、分页查询(支持多种数据...

tanghc
2017/08/22
5.6K
33

没有更多内容

加载失败,请刷新页面

加载更多

Spring Security 自定义登录认证(二)

一、前言 本篇文章将讲述Spring Security自定义登录认证校验用户名、密码,自定义密码加密方式,以及在前后端分离的情况下认证失败或成功处理返回json格式数据 温馨小提示:Spring Security...

郑清
32分钟前
3
0
php yield关键字以及协程的实现

php的yield是在php5.5版本就出来了,而在初级php界却很少有人提起,我就说说个人对php yield的理解 Iterator接口 在php中,除了数组,对象可以被foreach遍历之外,还有另外一种特殊对象,也就是继承...

冻结not
45分钟前
4
0
servlet请求和响应的过程

本文转载于:专业的前端网站➥servlet请求和响应的过程 1.加载 Servlet类被加载到Java虚拟机中,并且实例化。在这个过程中,web容器(例如tomcat)会调用Servlet类的公开无参构造函数,产生一...

前端老手
46分钟前
4
0
golang 1.13 errors 包来了,不用写“err 气功波”代码

引 这篇是对 errors 包 的姿势挖掘 气功波错误代码 从 http.Get()返回的错误 判断 syscall.ECONNREFUSED 错误.以前要对 go 标准库 error 结构有点熟悉,才能写出下面的代码 func CmdErr(err ...

guonaihong
49分钟前
28
0
喜玛拉雅已听书单

时间倒序排 书名 作者 状态 唐砖 孑与2 进行中 死灵之书(克苏鲁神话合集) 阿卜杜拉·阿尔哈萨德 进行中 赡养人类 刘慈欣 完结 赡养上帝 刘慈欣 完结 中国太阳 刘慈欣 完结 中国太阳 刘慈欣...

Alex_Java
50分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部