2

I am trying to create a small app using AngularJS which consists of users and issues posted by the users respectively.

I am trying to show issues when a particular user is clicked.

I have created the following code so far:

index.html

  <div class="container" ng-controller="issueContainer as issueTrack">

      <div class="leftContainer" ng-controller="issueForm as issueformCtrl">
          <issue-form></issue-form>

          <user-issues ng-repeat="issue in user.issues"></user-issues>    
      </div>

      <div class="rightContainer" ng-controller="userForm as userformCtrl">

          <form name="userform" ng-submit="userform.$valid && userformCtrl.addUsers()">
              <div class="form-group">
                <label for="addUser">Username</label>
                <input type="text" id="addUser" ng-model="userformCtrl.name" class="form-control" placeholder="Username">
              </div>
              <div class="form-group">
                <input type="submit" class="btn btn-primary" value="Submit" />
              </div>
          </form>

          <h3 class="usersTitle">Users</h3>

          <div class="users" ng-show="issueTrack.users.length">
              <div ng-repeat="user in issueTrack.users track by $index" value="{{user.username}}" ng-click="userformCtrl.userclickCtrl(user.username)">
                  {{user.username}}
              </div>
          </div>
      </div>
  </div>

app.js

(function(){

var app = angular.module("Issuetracker",[]);

var users=[];

if (localStorage.getItem('users')!==null){

    users = JSON.parse(localStorage.getItem("users"));
    console.log(users);
}

app.controller("issueContainer", function(){

    var issuetrack = this;
    this.users = users;

});

app.controller("userForm", function(){

    this.addUsers = function(){

        users.push({'username':this.name, 'issues':[]});
        this.name='';
        console.log(users);
        localStorage.setItem("users", JSON.stringify(users));
    };      

    this.userclickCtrl= function(data){

        var allUsers = JSON.parse(localStorage.getItem("users"));

        for(var i=0;i< allUsers.length;i++){

            if(allUsers[i].username == data){

                var userData = allUsers[i];
                break;
            }
        }
    };
});

app.controller("issueForm", function(){

    this.issue={};
    this.addIssues = function(){

        console.log(this.issue);
        var allUsers = JSON.parse(localStorage.getItem("users"));

        for(var i=0;i< allUsers.length;i++){

            if(allUsers[i].username == this.issue.User){

                allUsers[i].issues.push(this.issue);
                break;
            }
        }            

        this.issue={};

        localStorage.setItem("users", JSON.stringify(allUsers));
    };                
});

app.directive("userIssues", function(){

   return{

        restrict: 'E',
        templateUrl: 'userissues.html'
   }  
});

app.directive("issueForm", function(){

   return{

        restrict: 'E',
        templateUrl: 'issueform.html' 
   }  
});

})()

userissues.html

<div class="issues">
    <div ng-repeat="issue in user.issues">
        <h3>{{issue.Summary}}<span class="label label-primary" style="margin-left:2%">{{issue.Type}}</span></h3>
        <p>{{issue.Description}}</p>
    </div>
</div>

Whenever any user is clicked, userclickCtrl function is called where i am getting the user object from localStrorageand want to pass it to the userissues directive for the template.

Any leads would be appreciated!!!

rick
  • 1,869
  • 13
  • 22
Sukhmeet Singh
  • 130
  • 3
  • 13
  • Instead of `var userData = allUsers[i];` do `this.userData = allUsers[i]` and then access it in the template with `userForm.userData`. Just like you are doing with `issueForm.allUsers`. – Sergiu Paraschiv Apr 25 '16 at 09:16
  • yes..thats a good suggestion, but how can i pass this data to the directive (userissues). – Sukhmeet Singh Apr 25 '16 at 09:17
  • You'll have to show us some code for that directive then. But why do you need to pass it in there? Seems to me you need a different directive, not to push unrelated data in an existing one. – Sergiu Paraschiv Apr 25 '16 at 09:19
  • i have updated the code, included the userissues.html. I need to pass the array of issues to the template for displaying the data – Sukhmeet Singh Apr 25 '16 at 09:22
  • I can't understand the double ng-repeat one in the directive "call" -> and one in the template. Is that necessary? – rick Apr 25 '16 at 09:24
  • So you've got two separate controllers and you need to pass some data between them. This is what you need to read then: http://stackoverflow.com/questions/20181323/passing-data-between-controllers-in-angular-js – Sergiu Paraschiv Apr 25 '16 at 09:24
  • @rick its actually an array of objects that i am passing..it was an error that i made...thanks for pointing it out :) – Sukhmeet Singh Apr 25 '16 at 09:27
  • Ok nothing multidimensional :D – rick Apr 25 '16 at 10:07

3 Answers3

3

Not sure what you are using localStorage for, for sharing data between the controller and the directive? why not just use window.users.. But that is bad practice too.

There are two ways I can think of to make possible Controller-Directive communication.

1.Using event publish/subscribe ($on, $broadcast and $emit)

In the controller, use $scope.$broadcast('eventName',eventData) to send a message to all its child scopes, and in the directive, use $scope.$on('eventName',callback) to listen for it. The directive can also send message to the controller by using scope.$emit('eventName',eventData), please do some googling or refer to the official docs for more details.

If you can figure out ways to get the reference of the directive scope, use broadcast on the directive scope directly, it will be more efficient since the event will not be broadcast to irrelevant scopes.

Also, for efficiency concerns, when you use $emit in the directive, the $on callback in the controller should contain event.defaultPrevented = true;, to stop the propagation of the event into irrelevant higher class scopes.

2.Pass into the directive the reference of a object (we can call the object a handler/delegate/etc. not so sure) in controller via directive attribute.

I'm not sure whether it's a good practice but it's an effective practice that I often use.

E.g.

the directive:

js:

  app.directive('userIssues', function () {
      return {
          restrict: 'E',
          templateUrl: 'templates/user-issues.html',
          scope: {
              delegate: '='
          },
          link: function (scope, element, attr) {
              scope.issues = [];
              scope.delegate.addIssue = function (issue) {
                  scope.issues.push(issue);
                  console.log("An issue is added to the directive !!");
              };
              scope.issueClicked = function (id) {
                  scope.delegate.issueClicked(id);
              }  
          }
      }
  });

html:

 <div>
     {{issues}} //I will change when notified from controller
     <button ng-click="issueClicked(123)">
         click me to notify controller
     </button>
 </div>

the controller:

js:

app.controller('myController', function ($scope, $timeout) {
    $scope.issueDirectiveDelegate = {
        issueClicked: function (id) {
            console.log("received message from the directive that issue with id ", id, 'is clicked');
        }
    };

    $timeout(function(){
        getMoreIssues().then(function (issue) {
            $scope.issueDirectiveDelegate.addIssue(issue);
        });
    },1000);
});

html:

<div> <div>blahblah</div>
   <user-issues delegate="issueDirectiveDelegate"></user-issues>
</div>
Kevin
  • 2,775
  • 4
  • 16
  • 27
1

Don't know if I got your problem but maybe this is a possible solution.

You can pass the issue as argument to your directive in this way:

app.directive("userIssues", function(){

return{

    restrict: 'E',
    scope: { issue: '=' },
    templateUrl: 'userissues.html'

}
});

and you can use it like this:

<user-issues ng-repeat="issue in issues" issue="issue"></user-issues>

Try this fiddle for an example

Hope this is what you need

rick
  • 1,869
  • 13
  • 22
0

I am glad that @KevinWang and @Rick helped me with the answer i was looking for. Along with these, i found an awesome tutorial on Understanding Scope in Directives, which explains and complements @Rick's answer. I am sharing the link over here for elaborate understanding.

http://www.undefinednull.com/2014/02/11/mastering-the-scope-of-a-directive-in-angularjs/

Sukhmeet Singh
  • 130
  • 3
  • 13