1

I'm relatively new to angular and this is my first involved directive and I'm a little lost. I'm trying to create a re-usable list of items on separate tabs in my app. The list acts the same with the exception of how the items are displayed (handled by separate partials). I'm passing in attributes of many different types into the scope and I'm trying several different things based on what I've been reading. No matter what I've tried so far, I'm still having issues with the attributes binding correctly.

Below is my code and I'll try to explain it as best as possible, hopefully someone can tell me where I went wrong. The only things that appear to have bound correctly are the strings, the objects and functions are missing.

UPDATE: Turns out I needed to bind $scope.currentPage to the directive scope. Now ng-repeat is running, but other parts of the page that require access to the controller scope aren't working. I've updated the code below and continue looking into how to give access to the template.

Directive

var app = angular.module('main');

app.directive('itemList', function(){
  var linkFunction = function(scope, element, attributes){
     scope.$watch("query.value", function(){
         scope.filterFunction();  //pretty sure this never gets called on search
     });
  }

  return {
     restrict: 'E',
     replace: 'true',
     templateUrl: 'partials/directives/list-tab.html',
     link: linkFunction,
     scope: {
         filterFunction: "&filterFunction",
         searchPlaceholder: "@searchPlaceholder",
         pagedItems: "=pagedItems",
         clickFunction: "&clickFunction",
         classString: "@classString",
         infoTemplate: "@template",
         currentPage: "=currentPage"
     }
  }
});

index.html

//pagedCars is an array of nested objects that gets used by the template to display the information
//filterCars is a function
//carSelected is a function
<div class="available-items">
    <item-list filter-function="filterCars" search-placeholder="Search Cars" paged-items="pagedCars" current-page="currentPage" click-function="carSelected" class-string="car.carId==selectedCar.carId?'selected':''" template="'partials/cars/cars-template.html'"></item-list>
</div>

list-tab.html

<div class="form-group">
    <div class="search-field">
        <label for="searchField" id="searchLabel">Search</label><br/>
        <input type="text" ng-model="query.value" placeholder="{{searchPlaceholder}}"/>
    </div>
    <table class="table table-hover>
        <tbody>
            //currentPage is on the controller scope there's a separate control that allows the user to page through the pagedItems by updating the currentPage which would be reflected here
            <tr ng-repeat="item in pagedItems[currentPage]" ng-click="clickFunction($index) ng-class="classString">
                <td ng-include="infoTemplate"></td>
            </tr>
       </tbody>
    </table>
</div>

cars-template.html

<div class="row form-inline" id="{{item.carId}}">
    <div class="col-md-2">
       //this uses a method on the controller scope to format the url
       <img ng-src="{{retrieveIcon(item.iconUrl)}}" height="75px" width="75px"/>
    <div class="col-md-10">
       <div details-pane" id="carDetails" ng-include="'partials/cars/car-full-details.html'"></div>
       <div class="item-title">{{item.name}}</div>
       //the rest is just a table with more information about the item. item.description, item.mileage, etc...
    </div>
</div>

1 Answer 1

1

Try passing through your functions with their parentheses

<div class="available-items">
    <item-list filter-function="filterCars()" search-placeholder="Search Cars" paged-items="pagedCars" click-function="carSelected()" class-string="car.carId==selectedCar.carId?'selected':''" template="'partials/cars/cars-template.html'"></item-list>
</div>

Also FYI if your variable has the same name in your HTML as you want in your directive's scope you can just use the pass method. e.g.

scope: {
    filterFunction: "&",
    searchPlaceholder: "@",
    pagedItems: "@",
    clickFunction: "&",
    classString: "@",
    infoTemplate: "@template"
}
Sign up to request clarification or add additional context in comments.

2 Comments

thanks for the answer, I just posted an update to the question about something else. I had originally gone the route of adding the parentheses but I was running into issues. I think I may need to pull several methods off the controller and place them inside the directive
I may go back and attempt that once I square away the scoping issue

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.