如何从指令中的templateUrl运行$ scope函数?

时间:2014-09-27 01:22:02

标签: javascript angularjs firebase angularfire

这是一个向你展示所有代码的plnkr:http://plnkr.co/edit/0EdLH3gGoUrWcQkOeukt(我试图只展示什么是必要的,但我想展示正在进行的任务排序,因为这最终是我想要实现的目标)

如果从index.html触发而不是从repeat.html(templateUrl)触发,我可以在控制器中运行$ scope函数。 @Kato明确表示我需要使用一个转换但是在尝试了一段时间之后我无法理解它。当我设置transclude时,似乎没有任何东西出现在我身上:true并在repeat.html中添加ng-transclude。

//index.html
<body ng-controller="MainCtrl">
  <section>
    <form ng-submit="addTask(task); task.title=null">
      <input placeholder="Add Task" ng-model="task.title" />
    </form>
    <repeat-by-week collection="list"></repeat-by-week>
  </section>
</body>

//repeat.html (the templateUrl file) 
<ul class="tasks-list">
  <li ng-repeat="week in weeks">
    <ul>
      <li ng-repeat="day in week.days">
        <h4>{{day.time | date:"MMMM dd'th'" }}</h4>
        <ul>
          <li ng-repeat="task in day.items">
            <input type="checkbox" ng-model="task.complete" ng-change="isCompleteTask(task)">
            <input ng-model="task.title" ng-change="updateTask(task)">
            <button ng-click="deleteTask(task)">x</button>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>


   //the controller (I can access $scope.addTask but not update, delete, or complete)
   angular.module('app').controller('MainCtrl', function($scope, $firebase){
      var ref = new Firebase('https://plnkr.firebaseio.com/tasks');
      $scope.list = $firebase(ref).$asArray();

      $scope.addTask = function(newTask) {  
          $scope.list.$add({
            title: newTask.title,
            $priority: Firebase.ServerValue.TIMESTAMP,
            complete: false,
            completeTime: '',
            createTime: Firebase.ServerValue.TIMESTAMP
          });
        };

      $scope.deleteTask = function(task){
          alert('delete task was clicked');
          $scope.list.$remove(task);
        };

        $scope.updateTask = function(task){
          $scope.list.$save(task);
        };

        $scope.isCompleteTask = function(task){
          if(task.completeTime){
            task.completeTime = '';
          } else{
            task.completeTime = Firebase.ServerValue.TIMESTAMP;
          }
          $scope.list.$save(task);
        };  

    });

//the directive 
angular.module('app').directive('repeatByWeek', function($parse, $window) {
  return {
    restrict: 'E',
    replace: true,
    templateUrl: 'repeat.html',
    scope: {
      'master': '=collection'
    },
    link: function(scope, el, attrs) {
      // get the global moment lib
      var moment = $window.moment;
      scope.weeks = [];
      updateList();

      // whenever the source collection changes, update our nested list
      scope.master.$watch(updateList);

      function updateList() {
         scope.weeks = sortItems(parseItems(scope.master));
      }

      function sortItems(sets) {
        var items = [];
        // get a list of weeks and sort them
        var weeks = sortDescending(Object.keys(sets));
         for(var i=0, wlen=weeks.length; i < wlen; i++) {
           var w = weeks[i];
           // get a list of days and sort them
           var days = sortDescending(Object.keys(sets[w]));
           var weekEntry = {
             time: w,
             days: []
           };
           items.push(weekEntry);
           // now iterate the days and add entries
           for(var j=0, dlen=days.length; j < dlen; j++) {
             var d = days[j];
             weekEntry.days.push({
               time: d,
               // here is the list of tasks from parseItems
               items: sets[w][d]
             });
           }
         }
         console.log('sortItems', items);
         return items;
      }

      // take the array and nest it in an object by week and then day
      function parseItems(master) {
        var sets = {};
        angular.forEach(master, function(item) {
           var week = moment(item.$priority).startOf('week').valueOf();
           var day = moment(item.$priority).startOf('day').valueOf();
           if( !sets.hasOwnProperty(week) ) {
             sets[week] = {};
           }
           if( !sets[week].hasOwnProperty(day) ) {
             sets[week][day] = [];

           }
           sets[week][day].push(item);
         });
         console.log('parseItems', sets);
         return sets;
      }

      function sortDescending(list) {
        return list.sort().reverse();
      }

    }
  };
});

如何从repeat.html文件中的控制器访问$ scope.update,delete和complete函数(或者如果允许我访问这些函数,则将repeat.html文件移动到index.html)。

1 个答案:

答案 0 :(得分:3)

你已经有一个独立的范围,所以你也可以从控制器绑定你需要的功能,你可以这样做(只显示不同部分的相关代码):

Inside Index.html:

<repeat-by-week collection="list" update-task='updateTask(task)' delete-task='deleteTask(task)' is-complete-task='isCompleteTask(task)' ></repeat-by-week>

在您的指令中:

scope: {
  'master': '=collection',
  'deleteTask': '&',
  'isCompleteTask': '&',
  'updateTask': '&'
}

里面的repeat.html:

      <li ng-repeat="task in day.items">
        <input type="checkbox" ng-model="task.complete" ng-change="isCompleteTask({task:task})">
        <input ng-model="task.title" ng-change="updateTask({task:task})">
        <button ng-click="deleteTask({task:task})">x</button>
      </li>

Working Example