Как сделать тестирование A/B с помощью шаблонов AngularJS? - программирование

Как сделать тестирование A/B с помощью шаблонов AngularJS?

Я использую ng-templateplate и должен добавить возможность использовать разные шаблоны в процессе производства на основе пользовательской конфигурации.

.config(function config( $stateProvider ) {
 $stateProvider.state( 'demo', {
    url: '/demo',
    views: {
      "main": {
        controller: 'DemoCtrl',
        templateUrl: 'demo/demo.tpl.html'
      }
    }
  });
})

Моя текущая идея состоит в том, чтобы сделать dynamicUrl dynamic

templateUrl: 'demo/demo'+userService.getTemplate()+'.tpl.html'

и имеющий несколько файлов шаблонов, например:

  • demo.tpl.html(по умолчанию)
  • demo.b.tpl.html(версия b)
  • demo.c.tpl.html(версия c)

в то время как функция userService предоставляет версию шаблона для использования, например. ".b"

Вы согласны? Может быть, лучший/более простой подход к этой проблеме?

4b9b3361

Ответ 1

Стандарт AngularJS $routeProvider может принимать функцию для templateUrl. Но вы не можете вводить сервисы в эту функцию.

ui-router имеет параметр templateProvider, в который вы можете ввести то, что хотите, и вы должны вернуть что-то вроде этого для случая удаленного шаблона:

$stateProvider.state('demo', {
    templateProvider: function ($http, $templateCache, $stateParams, userService) {
        var url = 'demo/demo' + userService.getTemplate() + '.tpl.html';
        return $http.get(url, { cache: $templateCache }).then(function (response) {
            return response.data;
        });
    }
})

Ответ 2

Я не буду его обслуживать, потому что сервис будет частью js файла. Который будет статичным (при нормальном состоянии)

Вот как я это сделаю, в файле html я поставлю

window.abConfig = "defaultVersion";

В app.js я поставлю

.config(function config( $stateProvider ) {
 $stateProvider.state( 'demo', {
    url: '/demo',
    views: {
      "main": {
        controller: 'DemoCtrl',
        templateUrl: function() {
          return 'demo/demo' + window.abConfig + '.tpl.html';
        }
      }
    }
  });
})

Его тип Hacky, но он дает мне гибкость, чтобы решить, какую версию отображать для пользователя на уровне сервера. Мне может потребоваться написать логику до того, как пользователь загрузит контент на основе предыдущей активности пользователя, чего я не могу сделать с javascript на стороне клиента.

Ответ 3

Это может быть достигнуто с помощью стандартного angular, вам просто нужно посмотреть на него под другим углом!

Я бы предложил использовать $templateCache. Когда вы загружаете приложение, вы можете предварительно заполнить кеш $template выбранной версией пользовательских шаблонов.

Вы можете сделать что-то вроде

$templateCache.put("page-header.html", '<h1>MyAwesomeStartup</h1><h2>Buy now!?!?!</h2>');

Кроме того, если вы не возражаете против этой идеи, вы можете поместить шаблоны на страницу с помощью синтаксиса тега script, где id == templateURL, который вы используете в своем $routeProvider.

<script type="text/ng-template" id="page-header.html">
  <h1>MyAwesomeStartup</h1><h2>Buy now!?!?!</h2>
</script>

И ng загрузит его непосредственно из тега script.

Ответ 4

У меня есть другой способ, основанный на том же принципе

Кроме того, вам не нужно действительно запрашивать представление самостоятельно с помощью $http.

Итак, вы можете позволить ui-router обрабатывать эту часть.

Это проще, если у вас сложная архитектура вида.

.state('public.index', {
            url: '/',
            views: {
                "": {
                    template: '<div ui-view="abTestDummyView"></div>',
                    controller: ['landing', '$http', function(landing, $http) {
                        alert('Showing AB Test Landing #' + landing);
                        // increment landing stats
                        $http.get('http://stats.domain.com', {landing: landing});
                    }],
                    controllerAs: 'landingCtrl',
                },
                "[email protected]": {
                    templateProvider: ['landing', function(landing) {
                        // inject a view based on its name
                        return "<div ui-view=\"ab" + landing + "\"></div>";
                    }]
                },
                "[email protected]": {
                    template: "INJECTED AB1"
                    // replace by templateUrl: "/real path/"
                },
                "[email protected]": {
                    template: "INJECTED AB2"
                    // replace by templateUrl: "/real path/"
                }
            },
            resolve: {
                landing: function() {
                    return Math.floor((Math.random() * 2) + 1);
                }
            }
        })