修改一个用户的信息

  在本节中,你将看到另一个 API 端点,Angular 视图,控制器和路由的示例。

  我们将以类似的方式来处理这一部分。首先,我们创建两个 API 端点:一个用于获取具有 ID 的用户,另一个用于更新用户。然后,我们会在首页中为每个用户添加一个链接。当用户点击此链接时,他们将被重定向到填充了用户详细信息的表单。当他们点击保存,修改的信息将被保存,然后他们将被返回到主页。

1. 创建一个 API 端点

  这一步应该已经很熟悉了。我们将创建两个新路由:

GET /api/users/{id}
PUT /api/users/{id}

  所以,打开 routes->users.js。并添加以下路由:

router.get('/:id',function(req,res) {
    var collection = db.get('users');
    collection.findOne({
        _id: req.params.id
    },function(err,user) {
        if (err) throw err;
        res.json(user);
    });
});

  注意,这里我们有一个路由参数,由冒号(:id)表示。你可以使用 req.params.id 访问此参数的值。

  除此之外,这个路由配置的其余部分类似于你以前见过的。唯一的区别是,我们使用集合的 findOne 方法只返回一个对象。此方法的第一个参数是条件对象。因此,我们正在寻找一个 _id 等于 req.params.id 的文档。

  现在,创建另一个路由:

router.put('/:id',res) {
    var collection = db.get('users');
    collection.update({
        _id: req.params.id
    },{
        name: req.body.name,age: req.body.age,gender: req.body.gender
    },user) {
        if (err) throw err;
        res.json(user);
    });
});

  注意,我们使用 router.put 定义了这个路由。只有当有到此端点的 HTTP PUT 请求时,才会调用此处理程序。

  我们使用集合对象的 update 方法来更新文档。第一个参数是条件对象。我们正在尝试仅更新 _id 等于 req.params.id 的文档。第二个参数表示要更新的值。

  其余的很简单。

2. 创建一个编辑页

  首先,我们需要在首页上为每个用户添加一个链接。打开 partials->home.html 并更改 li,如下所示:

<li ng-repeat="user in users"> <a href="/#!/user/{{user._id}}"> {{user.name}} </a> </li>

  我们使用 Angular 绑定表达式根据用户的 ID 呈现动态网址。同样,请注意,为了与旧版本的浏览器兼容,URL 前面加上 /#!

  现在我们需要一个视图和一个表单来编辑用户。但是,我们已经有一个带表单的视图。所以,最好重用它。

  在 forusers.js 中,添加此新路由:

.when('/user/:id',{
    templateUrl: 'partials/user-form.html'
})

  因为我们还没有创建控制器,也没有设置路由的控制器。我们只是回顾一下我们的工作到这一点。

  返回浏览器,转到主页,并确保刷新页面。现在,每个用户都应该使用超链接来表示。点击任一用户。应该看到一个空表单,但是 URL 发生了变化

  在下一步中,我们将向此表单添加行为。我们将在加载时填充表单,并添加单击保存按钮的处理操作。

3. 实现编辑控制器

  现在我们有两个选择。我们可以创建一个新的控制器,如 EditUserCtrl,或重用现有的控制器(AddUserCtrl)。你认为最好的解决方案是什么? 答案是:没有最佳解决方案。这一切都取决于所处的环境中。如果两种情况(添加和编辑)有很多相似之处,只有很少的差别,那么创建一个处理这两种情况的控制器是有意义的。您需要一些条件语句来区分添加和编辑方案。另一方面,如果这两个场景中的行为相当不同,那么在一个控制器中最终会出现很多丑陋的条件语句。在这种情况下,最好将它们分成两个不同的控制器。

  在编写本教程的这一步之前,我开始重复使用相同的控制器,我不是很高兴其最终结果。所以,我决定把它们分成两个不同的控制器。

  在 forusers.js 中,创建一个新的控制器如下:

app.controller('EditUserCtrl',['$scope','$resource','$location','$routeParams',function($scope,$resource,$location,$routeParams) {
        var Users = $resource('/api/users/:id',{ id: '@_id' },{
            update: { method: 'PUT' }
        });
        Users.get({ id: $routeParams.id },function(user) {
            $scope.user = user;
        });
        $scope.save = function() {
            Users.update($scope.user,function() {
                $location.path('/');
            });
        }
    }
]);

  解释一下。

  首先,这个控制器,与我们的 AddUserCtrl 不同,有四个依赖。我们在这里有一个额外的依赖:$routeParams,我们用来访问路由中的参数(URL)。在这种情况下,要编辑的用户 ID 将是我们的路由参数。

  在这个控制器的主体中,首先我们使用 $resource 服务获取一个对象来使用我们的 API 端点。但这一次,我们以不同的方式使用 $resource 服务。

var Users = $resource('/api/users/:id',{
    update: { method: 'PUT' }
});

  第一个参数是到我们的端点的 URL。但是,这里我们有一个由冒号(:id)指示的路由参数。我们使用参数化路由,因为我们在本节前面创建的两个 API 端点包括路由参数。

GET /api/users/:id
PUT /api/users/:id

  此方法的第二个参数是一个对象,它为路由中的:id参数提供默认值。

{ id: '@_id' }

  这里,“@_id”告诉 Angular 在请求的对象中查找名为 _id 的属性。因此,当我们向 PUT /api/users/:id 发送请求时,Angular 将使用请求用户对象的 _id 属性,在路由中设置 :id 参数。

  $resource 方法的第三个参数用于扩展 $resource 服务。

{ update: { method: 'PUT' } }

  由于某些原因只有 Angular 的开发人员知道,默认情况下您不能使用 $resource 服务发送 HTTP PUT 请求。您需要通过添加使用 HTTP PUT 的更新方法来扩展它。

  接下来,我们使用 Users.get 获取具有给定 ID 的用户。

Users.get({ id: $routeParams.id },function(user) {
    $scope.user = user;
});

  这是在页面加载时填充表单。Users.get 的第一个参数提供了路由中的 :id 参数的值。我们使用 $routeParams.id,它允许我们访问浏览器地址栏中的参数。还记得编辑页面的路由声明?

.when('/user/:id',{
    templateUrl: 'partials/user-form.html'
})

  在那里,我们使用了一个路由参数(:id)。所以,我们可以访问它与 $routeParams

  在 Users.get 的回调方法。我们获取从服务器返回的用户并将其存储在 $scope 中。这样,使用 Angular 的双向绑定在后台运行,表单将自动填充我们的用户对象。还记得 ng-model? 我们将输入字段绑定到 $scope 上的用户对象的属性。输入字段中的任何更改都将反映在 $scope 中,反之亦然。

  最后,在控制器的主体中,我们定义了一个保存方法,当用户单击保存按钮时将调用该方法。

$scope.save = function() {
    Users.update($scope.user,function() {
        $location.path('/');
    });
}

  注意,在这里,我们使用 Users.update 而不是Users.save。这是我们在扩展 $resource 服务时定义的新方法。因此,这将向我们的 API 端点发出 HTTP PUT 请求。

  我们差不多完成了。新的控制器准备就绪。我们只需要在路由配置中引用它。更改路由配置如下:

.when('/user/:id',{
    templateUrl: 'partials/user-form.html',controller: 'EditUserCtrl'
})

  让我们来测试这个新功能。返回浏览器,然后刷新主页。选择其中一个用户。进行一些更改,然后单击保存按钮。一切都应该工作。

  在下一节中,我们将向用户管理应用添加删除功能,以构建完整的 CRUD 功能。

使用 MEAN 进行全栈开发基础篇——5、接着前面玩儿编辑的更多相关文章

  1. 关闭iOS原生MPVolumeView音频路由菜单

    我正在使用MPVolumeView允许用户在使用我的应用程序时控制他喜欢的音频路径.该代码显示了该视图:当用户点击音频路由按钮时,会出现一个带有可用选项的菜单.问题:显示音量视图的屏幕可能需要隐藏,因为我的应用程序处理各种事件,我想同时隐藏音频路由菜单我的问题:有没有人知道是否可以手动关闭MPVolumeView的音频路由选择菜单而无需用户按下取消按钮?解决方法在iOS8上,您可以使用以下使用私有API的代码

  2. ios – 当pod的新版本可用时,“pod update”是否会覆盖我的代码更改?

    我的更改会被覆盖吗?你能描述为什么是或为什么不?关于如何做到这一点.

  3. iOS:使用蓝牙音频输出(kAudioSessionProperty_OverrideCategoryEnableBluetoothInput)AudioSession

    >如果有可用的A2DP设备,我的音频路由将始终自动切换到kAudioSessionOutputRoute_BluetoothA2DP路由.如何防止此路线更改?我希望你们中的一些人可以帮助我解决这些问题.这对我对CoreAudio的整体理解,特别是AudioSession框架,真的有帮助.解决方法AudioSession是一项棘手的业务.1.BluetoothHFPaudiooutputisonlypossibleincaseofAudioSessionkAudioSessionCategory_PlayA

  4. ios – 什么是Sprite Kit中的SKSpinLockSync以及如何解决它

    我收到一个带有以下堆栈跟踪的错误报告,我不知道问题是什么.我已经看到这样的建议,这可能是由于在纹理图集中有一个发射器的图像,或者是在添加的同一个运行循环中移除了一个发射器,但我认为这些都不会发生.这是一个零星的问题,我无法再创造它.我只在bug报告中看到它.我很乐意帮忙.编辑:我现在意识到我在几种不同的情况下得到SKSpinLockSync问题,并不总是与发射器有关.我认为,我经常使用发射器看到它

  5. Carthage使用解决部分Swift运行时的问题

    1、首先,简单的利用Carthagehttps://github.com/Carthage/Carthage要求进行简单测试使用,建立一个demo测试2、可能由于xcode版本原因在:类似我执行时出现的错误:Argo.framework是用旧的编译器编译的(估计下载的那个包是用Xcode7编译因此在工程文件目录下需要执行将所有需要的包下载下来(原本执行update操作会直接将运行好的framewo

  6. pod install 与 pod update的区别

    podinstall是安装Podfile中指定版本的第三方库。podupdate是安装最新的版本,如果之前已经安装了,但是有新版本,会更新版本。

  7. Swift3.0 Swift2.3 获取IP地址 获取网关地址

    最近需要在Swift项目中获取路由器的网关地址,在网上找了半天的代码也没发现太多有价值的东西,而且大多都是OC代码,很少有Swift的相关代码,只找到了一个通过Swift代码获取设备IP的代码,最后实在没办法只能曲线救国了。下面上代码:思路就是把获取到的设备IP地址的最后一位手动修改为”1”,前面三位不需要修改,比如我的手机ip地址是192.168.31.212,所以网关地址就是192.168.31.1。最近苹果更新了Swift3.0,这里更新一下代码。

  8. Swift3.0服务端开发(二) 静态文件添加、路由配置以及表单提交

    今天博客中就来聊一下Perfect框架的静态文件的添加与访问,路由的配置以及表单的提交。也就是webroot的文件目录变地方了。后方的尾随闭包是对响应的处理。action的地址就是我们在服务器端配置的路由地址“127.0.0.1:8181/login”,而表单提交的方式是POST。

  9. Swift Web 开发之 Vapor - 路由二

    路由参数Vapor提倡使用类型安全的路由参数来接收数据,我们可以在路由方法中使用Swift类型来指定参数类型,Vapor会在内部解析并将参数返回给闭包以供使用,非常方便。Swift中处处有协议,路由参数也是如此,我们所见例子中的Int其实就是Vapor给实现了StringInitializable协议,当然String也已经默认实现。throw另外一大特性就是可以直接在路由中抛出异常,我们可以throw任何遵从Swift.Error协议的对象,当然Vapor已经为我们封装好了几个常用的Error来方便我们

  10. swift – Singleton模式和正确使用Alamofire的URLRequestConvertible

    如果是这样,我该如何设置经理的基础?此外,如果我使用这个管理器//这可以与上面显示的路由器结构一起工作?我是Alamofire图书馆的新手,迅速。然而,当您获得超过6或7例的情况下,这很快就会变得很快。首先,您的模型对象需要符合RouterObject协议。最后一个问题是您无法直接在Routerenum中存储baseURL或OAuthToken。但是,如果您只是使用默认会话触发网络,那么sharedInstance可能就足够了。

随机推荐

  1. Angular2 innerHtml删除样式

    我正在使用innerHtml并在我的cms中设置html,响应似乎没问题,如果我这样打印:{{poi.content}}它给了我正确的内容:``但是当我使用[innerHtml]=“poi.content”时,它会给我这个html:当我使用[innerHtml]时,有谁知道为什么它会剥离我的样式Angular2清理动态添加的HTML,样式,……

  2. 为Angular根组件/模块指定@Input()参数

    我有3个根组件,由根AppModule引导.你如何为其中一个组件指定@input()参数?也不由AppModalComponent获取:它是未定义的.据我所知,你不能将@input()传递给bootstraped组件.但您可以使用其他方法来做到这一点–将值作为属性传递.index.html:app.component.ts:

  3. angular-ui-bootstrap – 如何为angular ui-bootstrap tabs指令指定href参数

    我正在使用角度ui-bootstrap库,但我不知道如何为每个选项卡指定自定义href.在角度ui-bootstrap文档中,指定了一个可选参数select(),但我不知道如何使用它来自定义每个选项卡的链接另一种重新定义问题的方法是如何使用带有角度ui-bootstrap选项卡的路由我希望现在还不算太晚,但我今天遇到了同样的问题.你可以通过以下方式实现:1)在控制器中定义选项卡href:2)声明一个函数来改变控制器中的散列:3)使用以下标记:我不确定这是否是最好的方法,我很乐意听取别人的意见.

  4. 离子框架 – 标签内部的ng-click不起作用

    >为什么标签标签内的按钮不起作用?>但是标签外的按钮(登陆)工作正常,为什么?>请帮我解决这个问题.我需要在点击时做出回复按钮workingdemo解决方案就是不要为物品使用标签.而只是使用divHTML

  5. Angular 2:将值传递给路由数据解析

    我正在尝试编写一个DataResolver服务,允许Angular2路由器在初始化组件之前预加载数据.解析器需要调用不同的API端点来获取适合于正在加载的路由的数据.我正在构建一个通用解析器,而不是为我的许多组件中的每个组件设置一个解析器.因此,我想在路由定义中传递指向正确端点的自定义输入.例如,考虑以下路线:app.routes.ts在第一个实例中,解析器需要调用/path/to/resourc

  6. angularjs – 解释ngModel管道,解析器,格式化程序,viewChangeListeners和$watchers的顺序

    换句话说:如果在模型更新之前触发了“ng-change”,我可以理解,但是我很难理解在更新模型之后以及在完成填充更改之前触发函数绑定属性.如果您读到这里:祝贺并感谢您的耐心等待!

  7. 角度5模板形式检测形式有效性状态的变化

    为了拥有一个可以监听其包含的表单的有效性状态的变化的组件并执行某些组件的方法,是reactiveforms的方法吗?

  8. Angular 2 CSV文件下载

    我在springboot应用程序中有我的后端,从那里我返回一个.csv文件WheniamhittingtheURLinbrowsercsvfileisgettingdownloaded.现在我试图从我的角度2应用程序中点击此URL,代码是这样的:零件:服务:我正在下载文件,但它像ActuallyitshouldbeBook.csv请指导我缺少的东西.有一种解决方法,但您需要创建一个页面上的元

  9. angularjs – Angular UI-Grid:过滤后如何获取总项数

    提前致谢:)你应该避免使用jQuery并与API进行交互.首先需要在网格创建事件中保存对API的引用.您应该已经知道总行数.您可以使用以下命令获取可见/已过滤行数:要么您可以使用以下命令获取所选行的数量:

  10. angularjs – 迁移gulp进程以包含typescript

    或者我应该使用tsc作为我的主要构建工具,让它解决依赖关系,创建映射文件并制作捆绑包?

返回
顶部