2013-07-19 6 views
13

Ich benutze ng-boilerplate und muss die Möglichkeit hinzufügen, verschiedene Vorlagen in der Produktion zu verwenden, basierend auf der Benutzerkonfiguration.Wie man A/B Tests mit AngularJS Templates durchführt?

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

Meine aktuelle Idee ist, die templateUrl dynamische

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

und mit mehreren Template-Dateien zu machen, wie:

  • demo.tpl.html (default)
  • Demo. b.tpl.html (Version b)
  • demo.c.tpl.html (Version c)

während die userService-Funktion die zu verwendende Vorlagenversion bereitstellt, z. ".b"

Stimmen Sie zu? Gibt es vielleicht einen besseren/einfacheren Zugang zu diesem Problem?

+0

Nun ist der Dienst in der Config-Funktion verfügbar? –

+1

Sie haben recht, mein Vorschlag funktioniert nicht ... Keine Injektion möglich. –

+0

Ist der Benutzerservice ein Back-End-Verwaltungsportal, in dem sie ihre Standardoptionen "konfigurieren"? Die Daten müssen Preflight oder? –

Antwort

11

AngularJS-Standard $routeProvider kann Funktion für templateUrl annehmen. Sie können dieser Funktion jedoch keine Dienste hinzufügen.

ui-router hat templateProvider Parameter, in die Sie injizieren können, was Sie wollen, und Sie sollten so etwas wie dies für die Fern Vorlage Fall zurück:

$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

Dieser Standard Winkel erreicht, lassen sich mit, die Sie gerade es betrachten müssen aus einem anderen Blickwinkel!

Ich würde vorschlagen, die $templateCache verwenden. Wenn Sie die App laden, können Sie den $ template-Cache mit der ausgewählten Version der Benutzervorlagen füllen.

Sie können so etwas wie

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

auch tun, wenn Sie nicht auf die Idee, im Gegensatz Sie die Vorlagen in die Seite mit dem Skript-Tag-Syntax platzieren können, wo die ID == die templateURL Sie benutzen, um Ihre $ routeProvider.

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

Und ng wird es direkt aus dem Skript-Tag laden.

+0

scheint ein bisschen extrem und unmanagable für A/b-Tests. Das ist eine riesige Abwechslung von dem, wie man normalerweise "ng" Apps schreibt – electblake

+0

Das ist eine sehr interessante Lösung! Ich denke, das ist eine großartige Option, um unauffällig AB-Tests durchzuführen. – Vatsu1

2

Ich werde es nicht in Betrieb halten, weil Service ein Teil der js-Datei sein wird. Welche wird statisch (unter normalen Bedingungen)

Dies ist, wie ich es tun, In html Datei werde ich

window.abConfig = "defaultVersion"; 

In app.js setzen will ich

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

Seine Art setzen von Hacky Weg, aber es gibt mir Flexibilität zu entscheiden, welche Version für den Benutzer auf Server-Ebene anzuzeigen. Ich muss möglicherweise Logik schreiben, bevor der Benutzer den Inhalt basierend auf der vorherigen Aktivität des Benutzers herunterlädt, was ich nicht vom clientseitigen Javascript aus tun kann.

+0

Bonuspunkte für die Verallgemeinerung der Konfiguration – electblake

0

Ich habe eine andere Art und Weise auf dem gleichen Prinzip basiert

Außer Sie haben nicht wirklich verlangen, um die Ansicht, sich mit $ http.

So können Sie Ui-Router diesen Teil behandeln lassen.

Was ist einfacher, wenn Sie eine komplexe Ansicht Architektur haben.

.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); 
       } 
      } 
     }) 
Verwandte Themen