javascript - Angular 指令 - 选择下拉数组或对象模型

标签 javascript angularjs

我想要完成的是创建一个能够使用数组或对象模型生成选择下拉列表的指令。我从服务器获取一组对象,我想要生成仅使用“user_id”来显示我的选项的模板。这是我尝试过的:

HTML

<ng-select options="error.currentOrder.loggedPackages" selected="error.selected.user" object-field="user_id"></ng-select>

模板

<div class="select dropdown">
    <button data-toggle="dropdown"><% selected %><i class="fa fa-angle-down"></i></button>

    <ul ng-if="!objectField" class="dropdown-menu">
        <li ng-repeat="option in options" ng-click="selectOption($index)"><% option %></li>
    </ul>

    <ul ng-if="objectField" class="dropdown-menu">
        <li ng-repeat="option in options" ng-click="selectOption($index)"><% option[objectField] %></li>
    </ul>
</div>

Javascript

Application.directive('ngSelect', function () {
    return {
        restrict : 'E',
        replace : true,
        templateUrl : '/templates/directives/select.html',
        scope : {
            options: '=',
            selected: '=',
            objectField: '='
        },
        controller : ['$scope', function ($scope) {
            $scope.selectOption = function (index) {
                $scope.selected = $scope.options[index];
            }
        }],

        link: function(scope, elem, attrs)
        {
            console.log(scope.objectField);
            console.log('seleeeect');
        }
    }
});

Application.controller('ErrorReportingController', ['$scope', '$http', 'initData', 'ServerActions', function($scope, $http, initData, ServerActions) {

    var error = this;
    error.initData = initData;

    error.selected = {

    }

    error.submitOrder = function (orderID) {
        ServerActions.fetchData('/packing/error.action', {id : orderID}).then(
            function (response) {
                console.log(response.data);
                error.currentOrder = response.data;
            }
        )
    };

    console.log(error.initData);

}]);

最佳答案

所以,如果我理解正确的话,您需要带有动态模板的指令,这取决于 options 的类型和 object-field 属性的存在。另外,如果 object-field 是嵌套的,那就会很棘手:)

这是我解决这个问题的方法:

HTML

<html ng-app="app">

  <head>
    <link data-require="font-awesome@*" data-semver="4.3.0" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" />
    <script data-require="angular.js@1.4.6" data-semver="1.4.6" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-controller="appCtrl">
    <h3>Array of Strings: {{selectedString}}</h3>
    <app-select 
      options="stringModel"
      selected="selectedString"
    ></app-select>

    <h3>Array of Objects: {{selectedObject}}</h3>
    <app-select 
      options="objectModel"
      selected="selectedObject" 
      object-field="some.nested.field"
    ></app-select>
  </body>

</html>

JavaScript

angular.module('app',[]).
  controller('appCtrl', ['$scope', function($scope) {
    $scope.stringModel = ["First", "Second", "Third"];
    $scope.objectModel = [{some: {nested: {field: "First"}}}, {some: {nested: {field: "Second"}}}, {some: {nested: {field: "Third"}}}];
    $scope.selectedString = $scope.stringModel[1];
    $scope.selectedObject = $scope.objectModel[2];
  }]).
  directive('appSelect', ['$compile', function($compile) {
    return {
      scope: {
        'options': '=',
        'selected': '='
      },
      controllerAs: 'vm',
      bindToController: true,
      controller: [function() {
        this.visible = false;
        this.selectItem = function($index) {
          this.selected = this.options[$index];
          this.visible = false;
        };
      }],
      compile: function(template, attrs) {
        var isObject = !!attrs['objectField'],
            html =  '<div class="select dropdown">' +
                      '<button data-toggle="dropdown">' + 
                        '{{vm.' + (isObject ? 'selected.' + attrs.objectField : 'selected') + '}}' +
                        '<i class="fa fa-angle-down" ng-click="vm.visible=!vm.visible"></i>' + 
                      '</button>' +
                      '<ul class="dropdown-menu" ng-if="vm.visible">' +
                        '<li ng-repeat="option in vm.options track by $index" ng-click="vm.selectItem($index)">' +
                          '{{' + (isObject ? 'option.' + attrs.objectField : 'option') + '}}' +
                        '</li>' +
                      '</ul>' +
                    '</div>';              
        return function postLink(scope, el) {
          el.html(html);
          $compile(el.contents())(scope);
        };
      }
    }
  }]);

如果您需要通过URL加载模板,也是可以的。由于编译函数是在模板加载后调用的,因此您可以在编译函数中用其他内容替换一些占位符,例如“{{selected}}”和“{{option}}”:

...
      templateUrl: 'template.html',
      compile: function(template, attrs) {
        var isObject = !!attrs['objectField'],
            selected = isObject ? 'selected.' + attrs.objectField : 'selected',
            option = isObject ? 'option.' + attrs.objectField : 'option';
            html =  template.html().
              replace('{{selected}}', '{{vm.' + selected + '}}').
              replace('{{option}}', '{{' + option + '}}');
        return function postLink(scope, el) {
          el.html(html);
          $compile(el.contents())(scope);
        };
      }
...

template.html

<div class="select dropdown">
  <button data-toggle="dropdown">
    {{selected}}<i class="fa fa-angle-down" ng-click="vm.visible=!vm.visible"></i>
  </button>
  <ul class="dropdown-menu" ng-if="vm.visible">
    <li ng-repeat="option in vm.options track by $index" ng-click="vm.selectItem($index)">{{option}}</li>
  </ul>
</div>

笨蛋

您可以在此处查看有关动态模板的更多信息:

http://onehungrymind.com/angularjs-dynamic-templates/

关于javascript - Angular 指令 - 选择下拉数组或对象模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32904965/

相关文章:

javascript - 如何使用另一个文本区域编辑文本区域值?

javascript - Webpack sass css 文件在哪里

javascript - 为什么 for 循环在第一次迭代时停止?

c# - Microsoft JScript 运行时错误 : 'Sys' is undefined (in mvc3 c# razor)

javascript - 循环在所有 promise 响应完成之前完成

javascript - 从新选项卡中的应用程序启动新应用程序 Angular-Node

javascript - CSS/JavaScript : Make element top-most z-index/top-most modal element

javascript - ajaxcontroltoolkit 的 Ajax CDN 支持

javascript - 为视频而不是图像实现 Angular Masonry

javascript - AngularJS 可以在加载后编译由外部库附加的 HTML 吗?