germainelol
germainelol

Reputation: 3331

Angular - How to use a dynamic templateUrl for a directive?

So, for whatever reason, I am trying to create a slider, where the contents of each slide are different HTML templates. So instead of an image slider, you could say it's a HTML slider.

So in my HTML I just have this code, and the controls for the slider are also inside this HTML template:

<slide-template></slide-template>

And here is my entire slide module:

(function() {
    'use strict';

    angular
        .module('slideCtrl', [])

    .directive('slideTemplate', function() {
        return {
            restrict: 'E',
            templateUrl: 'views/slides/slide-1.html',
            replace: true,
            controller: 'slideController',
            controllerAs: 'slides'
        }
    })

    .controller('slideController', function() {

        var vm = this;

    });

})();

I'm not sure how to move forward with this, I've tried looking around but haven't found anything that I felt I could use. Inside the controller, I would like to have an array of slide template URLs and a corresponding variable to indicate the current slide:

slideUrl = [ 'views/slides/slide-1.html', 'views/slides/slide-2.html'];
slideNum = 0;

Ideally, I would then like my directive to use these variables to determine what variable it will use for templateUrl. So by default, you can see that slideNum is 0, meaning that I want to use slide1.html or slideUrl[0]. So, my templateUrl would be something like slideUrl[slideNum]. Of course, this can't be done as the directive wouldn't be able to access that data, so I'm not sure how to do this.

The end result would be that if you clicked one of the slide navigation icons, you would be updating the slideNum variable, which would instantly change the templateUrl used.

I guess I am essentially wanting a slider which doesn't rely on some images or something like that for content, but instead is a slider of actual HTML content.

Any ideas? If I haven't explained myself well enough, please let me know.

Upvotes: 0

Views: 317

Answers (3)

David Barker
David Barker

Reputation: 14620

You could move this to a link function and replace your compiled slide dynamically by adding them to the slideUrl array. This method is flexible enough to allow you to manage the slides in the controller, also you could potentially pass the slide urls to the directive through an scoped attribute.

.directive('slideTemplate', function($http, $compile, $templateCache) {
    return {
        restrict: 'E',
        replace: true,
        controller: 'slideController',
        controllerAs: 'slides',
        link : function(scope, el, attrs) {
            // Bind active slide number to controller scope
            scope.slides.num = 0;

            // Declare slide urls
            var slideUrl = [
                'views/slides/slide-1.html',
                'views/slides/slide-2.html'
            ];

            // Load a slide and replace the directives inner html
            // with the next slide.
            function loadSlide(template) {
                // Get the template, cache it and append to element
                $http.get(template, { cache: $templateCache })
                    .success(function(content) {
                        el.replaceWith($compile(content)(scope));
                    }
                );
            }

            // Progress to the next slide, this is bound to the
            // controllers scope and can be called from there.
            scope.slides.next = function() {
                var next = scope.slides.num + 1;
                var slide = slideUrl[next] ? next : slide;
                scope.slides.num = slide;

                loadSlide(slideUrl[slide]);
            }

        }
    }
});

Upvotes: 0

Arno_Geismar
Arno_Geismar

Reputation: 2330

hi I would solve it like this by creating a "main.html" template and in that:

//main.html

<div ng-if="slide == 1"> 
<ng-include src="'slide1.html'"/>
</div>

<div ng-if="slide == 2"> 
<ng-include src="'slide2.html'"/>
</div>

<div ng-if="slide == 3"> 
<ng-include src="'slide3.html'"/>
</div>

//controller

.controller('slideController', function() {
    $scope.slide = 1
   //logic to switch slides

    });

for animations on the slide transitions take a look at this code pen animations

Upvotes: 2

ndsmyter
ndsmyter

Reputation: 6605

I would suggest a main directive, where you would place the different slides on one page.

For instance, the main directive:

<div ng-include src="'slider0.html'" ng-if="slider%4==0"></div>
<div ng-include src="'slider1.html'" ng-if="slider%4==1"></div>
<div ng-include src="'slider2.html'" ng-if="slider%4==2"></div>
<div ng-include src="'slider3.html'" ng-if="slider%4==3"></div>

And then in the controller of the directive you set:

$scope.slider = 0;
// Some more logic like:
$scope.slider++;

Upvotes: 1

Related Questions