Mr. SHAW
Mr. SHAW

Reputation: 5

Add Directive programatically using $compile and pass data from scope,

I have created a directive named ng-chart as:

(function () {
'use strict';
angular
    .module('app')
    .directive('ngChart', ['$http', '$compile', 'DashboardService', '$q', '$timeout', '$modal', 'FlashService', function ($http, $compile, DashboardService, $q, $timeout, $modal, FlashService) {

        return {
            restrict: 'E',
            scope:
            {
                chartObj: "=?"
            },
            template: "<div style='position:relative;'>" +
                "<span style='position:absolute;top:0px;right: 27px;' id='spanMaxRestore' title='Maximize' ng-click='btnResizeClick()'><img style='width:18px;' src='../Dashboard/Images/bakupRestore.png' alt='Restore'/></span>" +
                "<span style='position:absolute;top:0px;right: 50px;' title='Configure' ng-click='btnSettingClick()'><img style='width:18px;' src='../Dashboard/Images/setting.png' alt='Configure'/></span>" +
                "<span style='position:absolute;top:0px;right:0px;' title='Close' onclick='this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode); return false;'><img src='/precisioncare/Dashboard/Images/dialog_close.png' alt='close chart'/></span><br/>" +
                "<div style='position:absolute; width:400px;'><img src='data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA=='/></div>" +
                "</div>",

            link: function (scope, iElement, iAttrs, ctrl)
            {
                scope.iElement = iElement;
                $(iElement).on('resize', function () {
                    scope.resize(iElement);
                });

                $(iElement).resizable();
                $(iElement).draggable();

                alert(scope.chartObj.dashUserElementId);

                scope.$watch('chartObj', function (chartData) {

                    if (chartData != "" && chartData != undefined) {
                        $timeout(function () {

                            var elem_id = scope.chartObj.dashUserElementId; //Element id.
                            var elem_data_source = scope.chartObj.dashUserElementDataSource; //Data query to retrive the data from database.
                            var displaytypeid = scope.chartObj.dashUserElementConfigDisplayTypeId; // Display type id of current element.


                            var divContainer = iElement.find('div');
                            scope.containerToDisplay = divContainer[1];
                            var dataObject = JSON.stringify({ "element_id": elem_id, "dataquery": elem_data_source, "Configurable": scope.chartObj.dashuserelement_date_range_origin });
                            //Return data series, Query parameter, and column name.
                            DashboardService.drawDashboardElement("getElementDataQuery", dataObject).then(function (response) {
                                var resultD = JSON.parse(response.d);
                                //If result is not empty then call drawChart method with passing parameter ResultD , displaytypeId and container to display.
                                if (resultD != undefined && resultD != "")
                                    scope.drawChart(resultD, displaytypeid, scope.containerToDisplay, elem_id);
                            },
                            function (error) {
                                // promise rejected, could log the error with: 
                                console.log('error', error);
                            });

                        }, 0);
                    }

                });

            },
            controller: function ($scope) {

                $scope.drawChart = function (resultD, displaytypeid, divId,elementId) {}  // some other charting code/functions here   }  }]); })();

The above snippet is of my directive which are called on my html view using ng-repeater as

<div ng-controller="DashboardController" style="width:100%; height:100%;">
    <div id="divChart" style="width:100%;" class="clearFloat">
        <ng-chart ng-repeat="adelement in UserConfigList" chart-obj="adelement" style='display: inline-block; margin: 20px; width: 400px; height: 450px; background-color: white'>
         </ng-chart>
    </div>  </div>

Now What i want to achieve is I want to add one more chart to my dashboard at runtime on charts series click event(I have used Highchart.js) for the same. So if user drags in or clicks on any section of the pie chart I want to draw one more ng-chart at runtime. here is what I am trying:

    var template = "<ng-chart chart-obj="+ $scope.chartObj +" style='display: inline-block; margin: 20px; width: 400px; height: 450px; background-color: white'></ng-chart>";

    var newElement = $compile(template)($scope);

    $("#divChart").append(newElement);

    $scope.insertHere = newElement;

But this does not seems to be working,anything missing/wrong in the code above ? I want to pass chart-Obj available in the current scope of the directive to new directive of same type(ng-chart)

Upvotes: 0

Views: 281

Answers (1)

Pepijn
Pepijn

Reputation: 1204

You're making one tiny mistake, angular doesn't $compile your object variable. Instead it looks for the variable on the scope by referencing it.

So your fix would be:

var template = '<ng-chart chart-obj="chartObj" style="display: inline-block; margin: 20px; width: 400px; height: 450px; background-color: white"></ng-chart>';

Next you would you want to create the compiled element first, and then add it to the $scope.

So like this:

var element = angular.element(template);

var compiled = $compile(element);

$('#divChart').append(element);

$timeout(function() {
    compiled($scope);
});

Also the $scope.$watch in your directive link function won't work, because it's a deep object, and you should add as a third parameter true if you want $scope.$watch. But because you defined the object in your scope as a two-way binded variable. You don't even need it.

Upvotes: 1

Related Questions