簡體   English   中英

在AngularJS中使用帶有自定義指令的不同控制器?

[英]Using different controllers with custom directive in AngularJS?

我創建了一個搜索框,用於兩個不同的視圖,一個用於搜索作業,另一個用於搜索公司。 我為兩者和單獨的服務制作了兩個獨立的控制器。

這是搜索框的html -

<span class="searchButton"><i class="fa fa-search fa-2x"></i></span>
<input ng-change="companies.search()" 
       ng-model="companies.searchTerm" 
       ng-keydown="companies.deleteTerm($event)" 
       type="text" id="search-box" 
       style="width: 0px; visibility:hidden;"/>

這是我用來設置樣式的腳本 -

<script type="text/javascript"> 
var toggleVar = true;
    $('.searchButton').on('click', function() {
        if(toggleVar) {
            $('.searchButton').animate({right: '210px'}, 400);
            $('#search-box').css("visibility", "visible");
            setTimeout(function() {
                $('.searchButton').css("color", "#444444");
            }, 200);
            $('#search-box').animate({ width: 185 }, 400).focus();
            toggleVar = false;
        }
        else {
            $('#search-box').animate({ width: 0 }, 400);
            $('.searchButton').animate({right: '25px'}, 400);
            setTimeout(function() {
                $('.searchButton').css("color", "#eeeeee");
            }, 300);
            toggleVar = true;
        }
    });

    $('#search-box').focusout(function() {
        if(!toggleVar) {
            $('#search-box').animate({ width: 0 }, 400);
            $('.searchButton').animate({right: '25px'}, 400);
            setTimeout(function() {
                $('.searchButton').css("color", "#eeeeee");
            }, 300);
            toggleVar = true;
        }
    });
</script>

控制器 -

angular.module('jobSeekerApp')
  .controller('CompaniesallCtrl', ['getAllCompanies', function (companiesService) {
    var ctrl = this;
    var count;
    ctrl.pageNumber = 1;
    ctrl.searchPageNumber = 1;
    ctrl.isSearching = false;
    ctrl.searchTerm = "";

    // Initial page load
    companiesService.getCompanies(ctrl.pageNumber)
      .then(function(response) {
        ctrl.companiesList = response.data.results;
        count = response.data.count;
        checkCount();
      }, function(error) {
        console.log(error);
      });

    // User clicks next button
    ctrl.getNext = function() {
      // If search is not being used
      if(ctrl.searchTerm === "" && ctrl.isSearching === false) {
        ctrl.pageNumber = ctrl.pageNumber + 1;
        companiesService.getCompanies(ctrl.pageNumber)
          .then(function(response) {
            ctrl.companiesList = ctrl.companiesList.concat(response.data.results);
            checkCount(); 
          }, function(error) {
            console.log(error);
          });
      }
      // If search is being used
      else {
        ctrl.searchPageNumber = ctrl.searchPageNumber + 1;
        companiesService.searchCompany(ctrl.searchPageNumber, ctrl.searchTerm)
          .then(function(response) {
            ctrl.companiesList = ctrl.companiesList.concat(response.data.results);
            checkCount();
          }, function(error) {
            console.log(error);
          });
      } 
    };

    // User backspaces to delete search term
    ctrl.deleteTerm = function (event) {
      if(event.keyCode === 8) {
        ctrl.searchTermLen = ctrl.searchTermLen - 1;
      }
      // If search box is empty
      ctrl.isSearching = ctrl.searchTermLen !== 0;
    };

    // User clicks search button
    ctrl.search = function() {
      ctrl.searchTermLen = ctrl.searchTerm.length;
      // If search box is empty, show normal results
      if(ctrl.searchTerm === "" && ctrl.isSearching === false) {
        ctrl.pageNumber = 1;
        companiesService.getCompanies(ctrl.pageNumber)
          .then(function(response) {
            ctrl.companiesList = response.data.results;
            count = response.data.count;
            checkCount();
          }, function(error) {
            console.log(error);
          });
      }
      // If search box is not empty, search the input
      else {
        ctrl.isSearching = true;
        ctrl.searchPageNumber = 1;
        companiesService.searchCompany(ctrl.searchPageNumber, ctrl.searchTerm)
          .then(function(response) {
            ctrl.companiesList = response.data.results;
            count = response.data.count;
            checkCount();
          }, function(error) {
            console.log(error);
          });
      }
    };

    // Function to hide and show next button
    function checkCount() {
      console.log(count);
      $(".nextButton").toggle(count > 10);
      count = count - 10;
    }
  }]);

我正在嘗試為此制定一個指令,因為所有這些代碼都是針對兩個視圖重復的。 但是如何使指令與不同的控制器交互。 我如何使這部分ng-change="companies.search()" ng-model="companies.searchTerm" ng-keydown="companies.deleteTerm($event)"不依賴於控制器。 我是角色的新手,我不確定這是正確的方法還是我應該讓代碼分開? 請幫忙。

服務器端搜索邏輯使其變得簡單

如果您的搜索邏輯可能駐留在服務器上,並且只需在URL中設置查詢變量就可以區分搜索作業或公司,那么就很容易了。 您可以使用帶有屬性的1個搜索指令來說明要搜索的模塊,並將其包含在您的HTTP請求中。

客戶端搜索邏輯略微更具角度

如果您需要針對每種類型的搜索使用不同的客戶端邏輯,請考慮這種方法,其中有1個常見search指令,以及每個自定義搜索的1個指令。

  1. 通用搜索指令控制視圖+通用搜索功能

  2. restrict: 'A'的搜索公司指令restrict: 'A'require: 'search'並執行特定於公司搜索的功能

  3. 一個也restrict: 'A'的搜索作業指令restrict: 'A'require: 'search'並執行特定於作業搜索的功能

概念是自定義搜索指令將其控制器/ api對象提供給公共搜索指令。 公共搜索指令處理視圖 - 控制器交互並調用提供的API函數以用於自定義搜索功能。

在Code中 ,這可能看起來像:

angular.module('SearchDemo', [])
.directive('search', function(){
    return {
        restrict: 'E',
        templateUrl: '/templates/search.tpl.html',
        controller: ['$scope', function($scope){
            $scope.results = [];

            this.setSearchAPI = function(searchAPI){
                this.api = searchAPI;
            };

            $scope.doSearch = function(query){
                $scope.results.length = 0;

                // here we call one of the custom controller functions
                if(this.api && angular.isFunction(this.api.getResults)){
                    var results = this.api.getResults(query);

                    // append the results onto $scope.results
                    // without creating a new array
                    $scope.results.push.apply($scope.results, results);
                }
            };
        }]
    };
})
.directive('searchCompanies', function(){
    return {
        restrict: 'A',
        require: ['search', 'searchCompanies'],
        link: function(scope, elem, attr, Ctrl){
            // here we pass the custom search-companies controller
            // to the common search controller
            Ctrl[0].setSearchAPI(Ctrl[1]);
        },
        controller: ['$scope', function($scope){
            // you need to design your common search API and 
            // implement the custom versions of those functions here

            // example:
            this.getResults = function(query){
                // TODO: load the results for company search
            };
        }]
    };
})
.directive('searchJobs', function(){
    return {
        restrict: 'A',
        require: ['search', 'searchJobs'],
        link: function(scope, elem, attr, Ctrl){
            // here we pass the custom search-jobs controller
            // to the common search controller
            Ctrl[0].setSearchAPI(Ctrl[1]);
        },
        controller: ['$scope', function($scope){
            // you need to design your common search API and 
            // implement the custom versions of those functions here

            // example:
            this.getResults = function(query){
                // TODO: load the results for job search
            };
        }]
    };
});

在模板中使用它看起來像:

<search search-companies></search>

<search search-jobs></search>

對一個指令進行多次搜索

如果您需要一個搜索指令來搜索公司和作業,則可以輕松擴展此概念。

改變是將搜索控制器的this.api變成一個數組。

angular.module('SearchDemo', [])
.directive('search', function(){
    return {
        restrict: 'E',
        templateUrl: '/templates/search.tpl.html',
        controller: ['$scope', function($scope){
            $scope.results = [];

            // this.api is now an array and can support 
            // multiple custom search controllers
            this.api = [];
            this.addSearchAPI = function(searchAPI){
                if(this.api.indexOf(searchAPI) == -1){
                    this.api.push(searchAPI);
                }
            };

            $scope.doSearch = function(query){
                $scope.results.length = 0;

                // here we call each of the custom controller functions
                for(var i=0; i < this.api.length; i++){
                    var api = this.api[i];
                    if(angular.isFunction(api.getResults)){
                        var results = api.getResults(query);

                        $scope.results.push.apply($scope.results, results);
                    }
                }
            };
        }]
    };
})
.directive('searchCompanies', function(){
    return {
        restrict: 'A',
        require: ['search', 'searchCompanies'],
        link: function(scope, elem, attr, Ctrl){
            // here we pass the custom search-companies controller
            // to the common search controller
            Ctrl[0].addSearchAPI(Ctrl[1]);
        },
        controller: ['$scope', function($scope){
            // you need to design your common search API and 
            // implement the custom versions of those functions here

            // example:
            this.getResults = function(query){
                // TODO: load the results for company search
            };
        }]
    };
})
.directive('searchJobs', function(){
    return {
        restrict: 'A',
        require: ['search', 'searchJobs'],
        link: function(scope, elem, attr, Ctrl){
            // here we pass the custom search-jobs controller
            // to the common search controller
            Ctrl[0].addSearchAPI(Ctrl[1]);
        },
        controller: ['$scope', function($scope){
            // you need to design your common search API and 
            // implement the custom versions of those functions here

            // example:
            this.getResults = function(query){
                // TODO: load the results for job search
            };
        }]
    };
});

在模板中使用它看起來像:

<search search-companies search-jobs></search>

您必須將數據源或服務傳遞給指令並從那里綁定事件。

<body ng-app="customSearchDirective">
  <div ng-controller="Controller">

  <input type="text" placeholder="Search a Company" data-custom-search data-source="companies" />
  <input type="text" placeholder="Search for People" data-custom-search data-source="people" />

  <hr>
  Searching In: {{ searchSource }}
  <br/>
  Search Result is At: {{ results }}
</div>
</body>

在此示例中,我使用data-source傳遞數組,但您當然可以使用服務。

那么你的指令應該使用scope屬性來分配你作為參數傳遞source的指令范圍。

您將獲得使用elem參數中的指令的輸入來綁定您想要的所有參數。

(function(angular) {
  'use strict';

  angular.module('customSearchDirective', [])


  .controller('Controller', ['$scope', function($scope) {
    $scope.companies = ['Microsoft', 'ID Software', 'Tesla'];
    $scope.people = ['Gill Bates', 'Cohn Jarmack', 'Melon Musk'];
    $scope.results = [];
    $scope.searchSource = [];
  }])


  .directive('customSearch', [function() {
    function link(scope, element, attrs) {
      element.on("change", function(e) {
        var searchTerm = e.target.value;
        scope.$parent.$apply(function() {
          scope.$parent.searchSource = scope.source;
          scope.$parent.results = scope.source.indexOf(searchTerm);
        });
      });
    }

    return {
      scope: {
        source: '='
      },
      link: link
    };
  }]);
})(window.angular);

使用scope.$parent我覺得有點hacky並限制使用該指令成為控制器的直接子項,但我認為這是一個讓你入門的好方法。

你可以嘗試一下: https//plnkr.co/edit/A3jzjek6hyjK4Btk34Vc?p = preview

這個例子中只有幾個注釋。

  • 從文本框中刪除焦點后,更改事件將起作用(而不是在您鍵入時)
  • 您必須搜索確切的字符串才能獲得匹配

希望能幫助到你。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM