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!!!

8
  • 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. Commented Apr 25, 2016 at 9:16
  • yes..thats a good suggestion, but how can i pass this data to the directive (userissues). Commented Apr 25, 2016 at 9: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. Commented Apr 25, 2016 at 9: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 Commented Apr 25, 2016 at 9:22
  • I can't understand the double ng-repeat one in the directive "call" -> <user-issues ng-repeat="issue in user.issues"></user-issues> and one in the template. Is that necessary? Commented Apr 25, 2016 at 9:24

3 Answers 3

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>
Sign up to request clarification or add additional context in comments.

Comments

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

1 Comment

glad to help, if need something else
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/

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.