Dynamic Directive TemplateUrls in AngularJS

Dynamic Directive TemplateUrls in AngularJS

I ran into a rather interesting problem while playing around with AngularJS and thought I'd share with other AngularJS professionals. I had a list of objects, and all of those objects shared a few common properties, while also having properties that were unique, based on the object type. My list contained a total of four unique object types. Based on that object type, I needed to display that object’s properties in a specific way. All of these objects needed to be displayed in a list utilizing Angular’s ngRepeat directive.

AngularJS

The easiest way to tackle this problem, and the most rudimentary, would be to simply put all the HTML required for each object type inside our ngRepeat and use ngShow and ngHide to display the correct template. The problem with this is not only cluttering our code, it injects a fair amount of useless HTML into our page and requires Angular to monitor a number of elements that won’t ever be displayed.

Instead, I wanted to create my own directive and dynamically set the templateUrl based on what type of object needed to be displayed.

.directive('dynamicObjectView', [function () {
    return {
        restrict: 'E',
        scope: { obj: '=' },
        templateUrl: function (element, attrs){ ... },
    };
}]);

This is when I noticed the templateUrl only allowed me access to the element, and attributes of the element my directive is attached to. When I got the list of objects via Angular’s $http service I could cycle through them and attach a property of templateUrl to each object based on what type that object is, and in turn, declare an attribute on my directive’s element to pass that templateUrl property into my templateUrl function. To me, that method felt too drawn out.

Instead, I wanted to make use of Angular’s ngInclude directive. I modified my directive, and instead of using templateUrl, I opted to use template and controller.

.directive('dynamicObjectView', [function () {
    return {
        restrict: 'E',
        scope: { obj: '=' },
        template: '',
        controller: ['$scope', function ($scope) {
            $scope.getTemplateUrl = function () {
                if ($scope.obj.typeID == 0)
                    return "AngularTemplate/GetObjectTemplate/Object0";
                else if ($scope.obj.typeID == 1)
                    return "AngularTemplate/GetObjectTemplate/Object1";
                else if ($scope.obj.typeID == 2)
                    return "AngularTemplate/GetObjectTemplate/Object2";
                else if ($scope.obj.typeID == 3)
                    return "AngularTemplate/GetObjectTemplate/Object3";
            }
        }]
    };
}]); 

By changing my directive to the code above I was able to use a single template for each object type, making updating those object type views extremely easy.


 

Next Steps

Review our case studies and engagements where we helped companies just like yours solve a variety of business needs.


About Oakwood

Since 1981, Oakwood has been helping companies of all sizes, across all industries, solve their business problems.  We bring world-class consultants to architect, design and deploy technology solutions to move your company forward.   Our proven approach guarantees better business outcomes.  With flexible engagement options, your project is delivered on-time and on budget.  11,000 satisfied clients can’t be wrong.

Like what you've read? Please spread the word!

Leave a Reply

Your email address will not be published. Required fields are marked *