2013-07-19 9 views
13

Я использую ng-templateplate и должен добавить возможность использовать различные шаблоны в процессе производства на основе пользовательской конфигурации.Как сделать A/B тестирование с помощью шаблонов AngularJS?

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

Моя текущая идея заключается в том, чтобы сделать templateUrl динамический

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

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

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

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

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

+0

Ну, это сервис, доступный в конфигурации? –

+1

Вы правы, мое предложение даже не работает ... Никакой инъекции невозможно. –

+0

Является ли пользователь сервисным сервером администрирования, где они «настраивают» свои параметры по умолчанию? Данные должны быть предвыборными? –

ответ

11

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

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; 
     }); 
    } 
}) 
1

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

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

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

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

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

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

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

+0

кажется немного экстремальным и неуправляемым для тестирования a/b. Это огромный отход от того, как «нормально» пишет ng apps – electblake

+0

Это очень интересное решение! Я думаю, что это отличный вариант для выполнения AB-тестирования ненавязчивым способом. – Vatsu1

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 на стороне клиента.

+0

бонусные баллы для обобщения конфигурации – electblake

0

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

кроме Вас не должны фактически запрашивать мнение самостоятельно с $ HTTP.

Таким образом, вы можете позволить ручке управления ui этой частью.

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

.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]lic.index": { 
        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); 
       } 
      } 
     })