3

I have created a directive for a search box which i want to use with different views. Here is the directive -

angular.module('jobSeekerApp')
  .directive('searchBoxDirective', function () {
    return {
      restrict: 'E',
      templateUrl: 'templates/searchbox-template.html',
    };
  });

template for the directive -

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

I want to use this directive on two views which look like this -

View 1 -

<div class="panel panel-default companies" ng-repeat="company in companies.companiesList">
    <div class="panel-heading text-center"><a ng-href="/companies/{{company.id}}" class="hvr-sink"><h3 class="well">{{company.company_name}}</h3></a></div>
    <div class="panel-body text-center flexcontainer">
        <div>Location: {{company.location}}</div>
        <div>Founded In: {{company.founded_year}}</div>
        <div ng-if="company.opening">Opening: Yes</div>
        <div ng-if="!company.opening">Opening: No</div>
        <div>Number Of Openings: {{company.no_openings}}</div>
    </div>
</div>

View 2 -

<div class="panel panel-default jobs" ng-repeat="job in jobs.jobsList">
    <div class="panel-heading text-center"><a href="{{job.career_url}}" target='_blank' class="hvr-sink"><h3 class="well">{{job.job_name}}</h3></a></div>
    <div class="panel-body text-center flexcontainer">
        <div>Company: {{job.company_name}}</div>
    </div>
</div>

As you can see i am using aliases companies and jobs in my views, due to this my directive is not able to affect the view it is contained in. If i use the companies or jobs in my template , then it works fine. So for example if change the template to -

<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;"/>

Then it works with the view associated with companies controller and similarly for jobs.

How can i use the directive with the respective controller instance? Thank you.

3 Answers 3

3

Create a simple view for Search

Create it's own controller

Search record by this controller in service and put data in service variable

this.searchResult = [];
this.search = function(searchText){
    // code to search
    this.searchResult = Result;    
}

Now where ever you want to use this result use the watch on this service variable in current controller, like:

$scope.$watch(function() { return servicename.searchResult ; }, function(newVal, oldval) { 
   if(newval != oldval){
       $scope.data = servicename.searchResult;
       /* Do the rest of stuff */
   }
}, true);
Sign up to request clarification or add additional context in comments.

1 Comment

I would highly discourage using a $watch unless absolutely necessary. They can be intensive if you get out of control with them and are not best practice.
2

Since the search function is asynchronous, I recommend avoiding the use of ng-change to invoke it. Instead use ng-click on the search icon.

<span class="searchButton" ng-click="$ctrl.searchFn()">
    <i class="fa fa-search fa-2x"></i>
</span>
<input ng-model="$ctrl.searchTerm" type="text" id="search-box">

In the directive, use isolate scope and bindToController.

app.directive('searchBoxDirective', function () {
    return {
      restrict: 'E',
      scope: { 'searchTerm': "=",
               'searchFn': "&"
             },
      controller: function () {},
      controllerAs: '$ctrl',
      bindToController: true,
      templateUrl: 'templates/searchbox-template.html'
    };
});

Usage

<search-box-directive search-term="companies.searchTerm"
                      search-fn="companies.search()" >
</search-box-directive>

<search-box-directive search-term="jobs.searchTerm"
                      search-fn="jobs.search()" >
</search-box-directive>

The search-term attribute creates a bidirectional binding from parent scope to the directive isolate scope. The search-fn attribute creates an expression binding from parent scope to isolate scope.

2 Comments

Thanks, this is i what i have been trying to do. I used ng-change because i wanted to display results as soon as the user starts typing, instead of clicking a button first. Also instead of passing search-term, search-fn separately, i passed the full object in the scope and used it like ng-model="$ctrl.obj.searchTerm" . And just curious how do i pass a function which takes an event like this ng-keydown="companies.deleteTerm($event)"?
2

Use isolate scope and explicitly pass the search term to your directive. Something like:

angular.module('jobSeekerApp')
  .directive('searchBoxDirective', function () {
    return {
      restrict: 'E',
      scope: {
        searchTerm: '=' <-- you can use '@' if you don't need two-way binding
      },
      templateUrl: 'templates/searchbox-template.html',
    };
  });

You didn't show where you are actually using your directive, but you would pass the scope property through an attribute (this is using your directive on a <div>):

<div search-box-directive search-term="companies.searchTerm"></div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.