更新模型和URL的正确方法是什么? [英] What's the correct way to update model and URL?

查看:104
本文介绍了更新模型和URL的正确方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我在同一页面上有以下元素:

Suppose I've got following elements on the same page:

  1. 过滤器"面板(类似于 http://www.imdb.com/search/name )
  2. 基于过滤器选项的项目
  1. Filters panel (something similar to http://www.imdb.com/search/name)
  2. Items based on filter options

我想实现以下逻辑:

  1. URL应该在路径(/appliedOptionA/appliedOptionB)中包含已应用的过滤器数据
  2. 当用户打开网站应用时,会从URL获取过滤数据,并更新过滤条件 面板和项目面板
  3. 当用户更改过滤器时,应用程序会更新URL并刷新项目
  1. URL should contain applied filter data in path (/appliedOptionA/appliedOptionB)
  2. When user opens site app get filter data from URL, updates filter panel and items panel
  3. When user changes filters app updates URL and refreshes items

第一个想法:配置ng-router,获取过滤器数据作为参数,将数据转换为模型,构造过滤器面板,加载项目,构造项目面板. 主要问题:用户更改过滤器时应如何使用?如果我将更新URL,它将触发具有不同参数的同一控制器,并重复该过程->将过滤器数据作为参数,将数据转换为模型,构造过滤器面板,项目等.我不需要它-我的模型和UI已经是最新的.

First idea: configure ng-router, get filter data as param, convert data to model, construct filters panel, load items, construct items panel. Main problem: how should it work when user changes filter? If I'll update URL it will trigger same controller with different param and repeat the process -> get filter data as param, convert data to model, construct filters panel, items and so on. I don't need it - my model and UI is already up to date.

我的问题:

什么是使模型和URL保持同步的正确方法? URL应该管理模型(ng-route)还是模型更改管理URL(如何?)?

what is the correct way to keep model and URL synchronized? Should URL manage model (ng-route) or model changes manage URL (how?) ?

推荐答案

我的建议是使用并使用代替ng-router,因为angular-ui-router为您提供了更大的灵活性,而且我认为它更易于使用.

My recommendation would be to use angular-ui-router and use that instead of ng-router since angular-ui-router gives you much more flexibility and is, in my opinion, easier to use.

鉴于您的主要问题",听起来您想拥有一个应用程序控制器(以下简称为"appCtrl")来处理所有更改并对其模型进行必要的更改.这种方法的主要缺点是它迫使您维护appCtrl中的"filteredItems"模型,这不是很有趣,并且可能导致不必要的麻烦.一种更简单的解决方法是让另一个控制器处理对URL的更改,而不是appCtrl本身.话虽这么说,让我向您展示如何实现这一目标.

Given your "Main Problem", it sounds like you want to have an single application controller (let's refer to this as the "appCtrl") handle all changes and make the necessary changes to its model. The main drawback with this approach is it forces you to the maintain the "filteredItems" model within the appCtrl, which is not fun and could lead to unnecessary headaches. An easier way to approach it would be to have another controller deal with those changes to the url, rather than the appCtrl itself. That being said, let me show you how you could accomplish this.

*警告:帖子很长! (但希望会有所帮助)*

因此,我还创建了一个演示示例,以防万一您只想要codez":

Because of this, I have also created a demo of everything I am about to discuss in case you "just want teh codez":

  • http://plnkr.co/edit/IMZZTE?p=preview
  • http://run.plnkr.co/fUddH83P2orHUsWj/#/

由于我们正在创建一个全新的应用程序,因此让我们从创建和配置该应用程序开始.

Since we are creating a brand new application, let's start with creating and configuring the application.

注意:请记住将angular-ui-router脚本加载到您的应用程序中并添加依赖项.

NOTE: Remember to load in the angular-ui-router script into your application and add the dependency.

app.js

var myApp = angular.module('myApp', ["ui.router"]);

现在我们有了app,让我们使用 ngApp指令.

Now that we have the app, let's add it to the index.html using the ngApp directive.

index.html

<body ng-app="myApp"></body>


在安装好应用程序后,让我们看看您在问题中解决的问题:


With the application in place, let's look at the issues you addressed in your question:

  • URL应该在路径(/appliedOptionA/appliedOptionB)中包含已应用的过滤器数据
  • 当用户打开站点应用程序时,从URL获取过滤器数据,更新过滤器面板和项目面板
  • 当用户更改过滤器时,应用程序会更新URL并刷新项目

您要执行的操作是创建一个状态.本质上,根据url模式激活/禁用状态.给定特定的模式,您可以告诉应用程序如何操作(使用控制器)以及外观如何(使用模板).在继续之前,请确保参考 URL路由,这将对您有所帮助带有网址格式.

What you want to do is create a state. Essentially, a state is activated/deactivated based on the url pattern. Given a particular pattern, you can tell the application how to act (using a controller) and what to look like (using a template). Before continuing, make sure to reference url routing, which will help with url patterns.

我们需要:

  • 给州起一个名字("filteredItems")
  • 提供网址格式
  • 提供控制器
  • 提供templateUrl
  • give the state a name ("filteredItems")
  • provide a url pattern
  • provide a controller
  • provide a templateUrl

让我们配置应用程序,以及:

Let's configure the application, as well as:

  • 在网址不存在的情况下提供默认的网址路由
  • 添加默认的home状态
  • 添加filteredItems状态
  • provide a default url route in the event the url does not exist
  • add a default home state
  • add the filteredItems state

app.js

myApp.config(function($stateProvider, $urlRouterProvider){

// default url - used if url pattern is not recognized
 $urlRouterProvider.otherwise('/'); 

 $stateProvider
    .state('home', { // default state
      url: '/'
    })
    .state('filteredItems', { // give the state a name
        url: "/:appliedOptionA/:appliedOptionB", // provide the url pattern
        controller: 'FilteredItemsCtrl', // controller to use for this state
        templateUrl: "filteredItems.html" // url for the template
    });
});

我们现在已经配置了该州的url以接受参数(appliedOptionAappliedOptionB).使用 $stateParams service ,我们可以创建一个filteredItemsCtrl并负责过滤数据.

We have now configured the state's url to take parameters (appliedOptionA and appliedOptionB). Using $stateParams service, we can create a filteredItemsCtrl and have that be responsible for filtering out the data.

但是在执行此操作之前,我们应该创建一个服务.使用Angular时, 避免 使用控制器来维护数据,因为可以创建/销毁它们.最佳做法是改为使用服务.话虽如此,让我们创建一个令人惊叹的itemService:

But before we do that, we should create a service. When using Angular, AVOID using controllers to maintain data since they can be created/destroyed. Best practice is to use services instead. That being said, let's create an amazing itemService:

itemService.js

angular.module('myApp').factory('itemService', itemService);

function itemService (){
  var items = {
      appliedOptionA: [ 'Item 1', 'Item 2', 'Item 3' ],
      appliedOptionB: [ 'Item 4', 'Item 5', 'Item 6' ]
    };

    function getItems (){
      return items;
    }

    return {
      getItems: getItems
    }
}

太好了吧?我很高兴您也这么认为!

Gorgeous right? I am glad you think so too!

现在有了服务,我们可以创建FilteredItemsCtrl.我们还将新创建的itemService注入到FilteredItemsCtrl中,以便它能够访问数据.

Now that we have a service, we can create the FilteredItemsCtrl. Let's also inject our newly created itemService into the FilteredItemsCtrl, so its able to access the data.

注意:请记住将$stateParams服务作为依赖项注入!

NOTE: Remember to inject the $stateParams service as a dependency!

filteredItemsCtrl.js

angular.module('myApp').controller('FilteredItemsCtrl', filteredItemsCtrl);

filteredItemsCtrl.$inject = ['$stateParams', '$scope', 'itemService'];

function filteredItemsCtrl ($stateParams, $scope, itemService){
  var items = itemService.getItems(); // get items from service

    // filter items
    $scope.appliedOptionA = items.appliedOptionA.filter(function (item){
      if ($stateParams.appliedOptionA){
        return item.toLowerCase().indexOf($stateParams.appliedOptionA) > -1 ||
               item.indexOf($stateParams.appliedOptionA) > -1
      }
    });
    $scope.appliedOptionB = items.appliedOptionB.filter(function (item){
      if ($stateParams.appliedOptionB){
        return item.toLowerCase().indexOf($stateParams.appliedOptionB) > -1 ||
               item.indexOf($stateParams.appliedOptionB) > -1
      }
    });
}

当我们定义状态的url时,我们将其设置为:url: "/:appliedOptionA/:appliedOptionB".这意味着$stateParams将使用AppliedOptionA和AppliedOptionB属性填充.这也意味着每次URL更改时,都会创建 new ,因此您不必维护应用程序的模型!

When we defined our state's url, we set it up like: url: "/:appliedOptionA/:appliedOptionB". This means the $stateParams will be populated with appliedOptionA, appliedOptionB properties. Also this means every time the URL changes, a new filteredItemsCtrl is created, thus, you do not have to maintain the application's model!

在忘记之前,我们还需要为此状态创建一个模板.

Before we forget, we also need to create a template for this state.

filteredItems.html

<div>
  <div>
     <span>Filtered Option A Items:</span>
    <ul>
      <li ng-repeat="optionItemA in appliedOptionA">
        {{ optionItemA }}
      </li>
    </ul>
  </div>

  <div>
    <span>Filtered Option B Items:</span>
    <ul>
      <li ng-repeat="optionItemB in appliedOptionB">
        {{ optionItemB }}
      </li>
    </ul>
  </div>
</div>

在创建状态,filteredItemCtrl和视图之后,剩下的就是包括ui-view指令,以使状态的模板正确显示:

With the state, filteredItemCtrl, and view created, all that is left is to include the ui-view directive, in order for the state's template to properly appear:

index.html

 <body ng-app="myApp"
      ng-controller="MyAppCtrl">
      <div>
        <div>
            Applied Option A: <input ng-model="appliedOptionA" />
          </div>
          <div>
            Applied Option B: <input ng-model="appliedOptionB" />
          </div>

          <button type="button"
                  ng-click="filter()">Search</button>
      </div>

      <!-- where the state template goes -->
      <div ui-view></div>
    </body>

仅此而已!很抱歉发布了很长的帖子,但希望您能从中找到有用的信息!如果您有任何问题,请告诉我!

That is all there is to it! Sorry about the long post, but hopefully you found this informative! Please let me know if you have any issues!

这篇关于更新模型和URL的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆