Tikhon
Tikhon

Reputation: 1024

AngularJS Custom Directive Accessing Scope Data

We are brand new to AngularJS but are trying to display some html tooltips from a custom directive in Angular and since new new to this technology are struggling to come up with a proper solution to this issue.

We had a version of a solution running using Angular+Web API, but discovered the mouseover events and CRUD functionality belonged in directives instead of the controller, so we're pulling that out and re-building.

Currently in a Plunker POC, we have:

  1. Loaded a very small SVG file.
  2. Loaded a small json data file.
  3. For each SVG element, attached a custom directive hover event
  4. When a particular element is hovered, an alert() executes with the element id.

SVG Sample:

<g id="f3s362c16">
<rect x="577.5" y="533.2" fill="none" width="22.2" height="25.7"/>
<polyline fill="none" stroke="#CEDEED" stroke-width="0.6468" stroke-miterlimit="10" points="590.4,559 577.5,559 577.5,533.2 
    599.5,533.2 599.5,550   "/>
<text transform="matrix(1 0 0 1 590.9561 557.4941)" font-family="arial, sans-serif" font-size="5.1408">362.16</text>

Json sample:

{"Id":1,"empNum":null,"fName":" Bun E.","lName":"Carlos","refacName":null,"deptId":"Drums","divisionId":null,"jobDesc":"Drummer","seatTypeId":1,"officeCode":null,"phone":null,"seatId":"f3s362c12 ","oldSeatId":null,"floor":3,"section":"313 ","seat":"12 "}

we have a scope variable for the json defined in the html file:

{{ **empData** }}

Controller file data load:

 var onLoadComplete = function (response) {
   $scope.**empData** = response.data;
 }

 //error
 var onError = function(reason) {
   $scope.error = "Could not get the data";
 }

 //get data
 $http.get('data.json')
    .then(onLoadComplete, onError);

Directive to load SVG and add directive to cube element

//directive loads SVG into DOM
angular.module('FFPA').directive('svgFloorplan', ['$compile', function ($compile) {
return {
    restrict: 'A',

    templateUrl: 'test.svg',
    link: function (scope, element, attrs) {

        var groups = element[0].querySelectorAll("g[id^='f3']")
        angular.forEach(groups, function (g,key) {
            var cubeElement = angular.element(g);
            //Wrap the cube DOM element as an Angular jqLite element.
            cubeElement.attr("cubehvr", "");
            $compile(cubeElement)(scope);
        })
      }
    }
}]);

Cube Hover Directive:

angular.module("FFPA").directive('cubehvr', ['$compile', function ($compile) {
return {
    restrict: 'A',
    scope: true,
    empData: "=",

    link: function (scope, element, attrs) {

        //id of group 
        scope.elementId = element.attr("id");

        //function call from line 63
        scope.cubeHover = function () {

            //groupId is the id of the element hovered over.
            var groupId = scope.elementId;

            alert(scope.elementId);
            //Here need to get access to scope empdata json to filter and 
            //match to the cube #.
            //IE: If I hover over 362.12, return json data for
            //{"Id":1,"empNum":null,"fName":" Bun E.","lName":"Carlos","refacName":null,"deptId":"Drums","divisionId":null,"jobDesc":"Drummer","seatTypeId":1,"officeCode":null,"phone":null,"seatId":"f3s362c12 ","oldSeatId":null,"floor":3,"section":"313 ","seat":"12 "}
            //since we don't have access to the empData scope variable, cannot run filter.
            var thisData = empData.filter(function (d) {
              return d.seatId.trim() === groupId
            });
            //after we get a match, we need to display a tooltip with save/cancel buttons.


        };
        element.attr("ng-mouseover", "cubeHover()");
        element.removeAttr("cubehvr");
        $compile(element)(scope);
    }
}
}]);

We are getting the alert for the specific cube hover, but I think we need to get access to the page scope variable to do the filter:

var thisData = empData.filter(function (d) {
              return d.seatId.trim() === groupId

});

Once we get a match, I think we should be able to append html to our div tag and display it:

   <div class="tooltip"></div>

Angular:

tooltip.html("Name: " + thisData[0].fName + " " + 
thisData[0].lName  + "<br>Role: " + 
thisData[0].jobDesc + "<br>Extension: " + 
thisData[0].phone)//+ "<br>Avatar: <img src=" + thisData[0].Avatar + ">")
.style("top", (d3.event.pageY + 15) + "px").style("left", (d3.event.pageX + 0) + "px")
.style("visibility", "visible");

At this point, we're not sure how to get the view/page scope variable {{empData}} in the hover (2nd) directive since we're already passing cubeHvr the directive:

angular.module("FFPA").directive('cubehvr', ['$compile', function ($compile)       {...}      

Thanks in advance for any direction you might give us here.

Upvotes: 2

Views: 603

Answers (1)

fingerpich
fingerpich

Reputation: 9330

Define a service as the following code

angular.module('FFPA')
.service('dataService', function () {
    this.getData = function(){
        return $http.get('data.json').then(function(){
             return response.data;
           }, function(){
               return {err:"Could not get the data"};
           }
        );
    }
});

and then inject it to any directive, controller, component or service.

angular.module("FFPA").directive('cubehvr', ['$compile','dataService', function ($compile,dataService) {
return {
    restrict: 'A',
    scope: true,
    link: function (scope, element, attrs) {

        dataService.getData().then(function(data){
            scope.emData=data;
        })

Upvotes: 1

Related Questions