简体   繁体   English

在自己的指令中包装Angular.js ui-bootstrap或ui-select指令

[英]Wrapping Angular.js ui-bootstrap or ui-select directives in own directive

I am creating a big Angular.JS application which uses some third party modules like ui-select and ui-bootstrap. 我正在创建一个大的Angular.JS应用程序,它使用一些第三方模块,如ui-select和ui-bootstrap。 To avoid repeating myself I started to create directives which are wrapping for example ui-select code and the logic to retrieve / search for data. 为了避免重复我自己,我开始创建包含例如ui-select代码和检索/搜索数据的逻辑的指令。

Goal : The goal was to create a directive which can be used in the template like that, without duplicating code in controllers: 目标 :目标是创建一个可以在模板中使用的指令,而无需在控制器中复制代码:

<tq-car-select ng-model="model.car"></tq-car-select>

What I try to avoid: 我试图避免的:

<select ng-options="car.id as car.name for car in cars"></select>

and duplicate following code in all controllers which are using the select: 并在使用select的所有控制器中复制以下代码:

$scope.cars = carResource.query();
$scope.$watch('model'), function (newValue, oldValue) {
    $scope.cars = carResource.query({model: $scope.model});
});

I created directives for that kind of select fields. 我为那种选择字段创建了指令。

Actual Example with ui-select : ui-select的实际示例

tq-lead-select.html: TQ铅select.html:

<ui-select ng-model="$parent.tqModel" style="display: block">
    <ui-select-match placeholder="tippen ...">{{$select.selected.bezeichnung}}</ui-select-match>
    <ui-select-choices repeat="lead in leads | filter:{bezeichnung: $select.search}">
        <div ng-bind-html="lead.bezeichnung | highlight: $select.search"></div>
    </ui-select-choices>
</ui-select>

tqLeadSelect.ts (TypeScript): tqLeadSelect.ts(TypeScript):

export function tqLeadSelect(tqLeadSelects): ng.IDirective {

var dir: ng.IDirective = {};

dir.scope = {
    tqModel: '=',
    tqCompany: '='
};

dir.restrict = 'E';
dir.templateUrl = '/js/templates/leadApp/tq-lead-select.html';
dir.replace = false;

dir.controller = function ($scope: any) {
    if (tqLeadSelects != null && $scope.tqCompany != null) {
        $scope.leads = tqLeadSelects.getLeadsFromFirma({ id: $scope.tqCompany });
    }

    $scope.$watch('tqCompany', (newValue, oldValue) => {
        if (newValue === oldValue) return;

        $scope.leads = tqLeadSelects.getLeadsFromFirma({ id: $scope.tqCompany });
    }, true);
}

return dir;
}

tqLeadSelect.$inject = ['tqLeadSelects'];

Problems : 问题

  • I need isolated scope, because some views use multiple instances of one field. 我需要隔离范围,因为一些视图使用一个字段的多个实例。
  • I am using the isolated scope variable tqModel which is set by the ngModel of the ui-select directive 我正在使用孤立的范围变量tqModel,它由ui-select指令的ngModel设置
  • I would like to use ng-required without creating a tq-required scope variable on tqLeadSelect directive 我想在不使用tqLeadSelect指令创建tq-required范围变量的情况下使用ng-required

Questions : 问题

  • Am I doing it right? 我做得对吗? Are there better ways achieving my goals? 有没有更好的方法来实现我的目标?
  • how are you defining select fields with supporting controller code for retrieving data and additional functions? 如何定义具有支持控制器代码的选择字段以检索数据和附加功能?

One solution would be to add a directive which extends the existing directive. 一种解决方案是添加一个扩展现有指令的指令。

I created a Plunker with an example: http://plnkr.co/edit/9IZ0aW?p=preview 我用一个例子创建了一个Plunker: http ://plnkr.co/edit/9IZ0aW?p = preview

Following Code: 以下代码:

HTML: HTML:

<ui-select ng-model="address.selected" theme="bootstrap" ng-disabled="disabled" reset-search-input="false" style="width: 300px;">
  <ui-select-match placeholder="Enter an address...">{{$select.selected.formatted_address}}</ui-select-match>
  <ui-select-choices repeat="address in addresses track by $index" refresh="refreshAddresses($select.search)" refresh-delay="0">
    <div ng-bind-html="address.formatted_address | highlight: $select.search"></div>
  </ui-select-choices>
</ui-select>

Controller: 控制器:

$scope.address = {};
$scope.refreshAddresses = function(address) {
  var params = {
    address: address,
    sensor: false
  };
  return $http.get(
    'http://maps.googleapis.com/maps/api/geocode/json', {
      params: params
    }
  ).then(function(response) {
    $scope.addresses = response.data.results
  });
};

can be simplified by using a configuration directive: 可以使用配置指令简化:

<ui-select ng-model="adress.selected" tq-select></ui-select>

Controller is now empty! 控制器现在是空的!

Directive: 指示:

app.directive("tqSelect", function($http) {

  return {
    restrict: "A", // Attribute
    require: ["uiSelect", "ngModel"],

    compile: function compile(tElement, tAttrs, transclude) {

      // Add the inner content to the element
      tElement.append('<ui-select-match placeholder="Enter an address...">{{$select.selected.formatted_address}}</ui-select-match>\
      <ui-select-choices repeat="address in addresses track by $index" refresh="refreshAddresses($select.search)" refresh-delay="0">\
        <div ng-bind-html="address.formatted_address | highlight: $select.search"></div>\
      </ui-select-choices>');

      return {
        pre: function preLink(scope, iElement, iAttrs, controller) {},
        post: function postLink(scope, iElement, iAttrs, controller) {

          // logic from controller
          scope.address = {};
          scope.refreshAddresses = function(address) {
            var params = {
              address: address,
              sensor: false
            };
            return $http.get(
              'http://maps.googleapis.com/maps/api/geocode/json', {
                params: params
              }
            ).then(function(response) {
              scope.addresses = response.data.results
            });
          };
        }
      }
    }
  }
});

The directive is the actual tricky part. 该指令是实际棘手的部分。 I am using a not trivial logic in the compile function. 我在编译函数中使用了一个非常简单的逻辑。 First I add the required markup for the ui-select directive. 首先,我为ui-select指令添加所需的标记。

Then in the post-link function I added the logic which is normally in the controller (or in the link()-function). 然后在后链接函数中,我添加了通常在控制器中(或在link() - 函数中)的逻辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM