2013-07-19 33 views
13

我正在使用ng-boilerplate,並且必須根據用戶配置添加在生產中使用不同模板的可能性。如何使用AngularJS模板進行A/B測試?

.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

那麼這個服務在config函數中可用嗎? –

+1

你說得對,我的建議甚至不起作用......沒有可能的注射。 –

+0

用戶服務是他們「配置」其默認選項的後端管理門戶嗎?數據需要預檢嗎? –

回答

11

AngularJS標準$routeProvider可以接受templateUrl的函數。但是你不能在這個函數中注入服務。

ui-routertemplateProvider參數可以在其中注入你想要什麼,你應該返回像這樣的遠程模板案例:

$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>'); 

此外,如果你不反對的想法,你使用腳本標記語法,可以將模板到頁面,你在使用id ==的templateURL您$ routeProvider。

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

而ng會直接從腳本標記中加載它。

+0

似乎有點極端,不適合a/b測試。這與「正常」寫入應用程序的方式有很大差異 – 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'; 
     } 
     } 
    } 
    }); 
}) 

先河的方式,但它使我可以靈活地決定在服務器級別向用戶顯示哪個版本。我可能需要在用戶根據用戶以前的活動下載內容之前編寫邏輯,這是我無法從客戶端JavaScript執行的。

+0

普及配置的積分 – electblake

0

我已經基於相同原理

除非你用不同的方式不必實際要求自己的觀點與$ 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); 
       } 
      } 
     }) 
相關問題