2017-06-08 3 views
1

Ich habe eine Angular 1.5.9 Web-Anwendung und ein Node.js/Sails.js 0.12 Backend. Inside Angular Läuft UI Router 0.4 zur Handhabung von Zuständen.Parsing UI Router zu URLs ohne Angular

Die Zustandsdefinitionen könnte wie folgt aussehen (ganz Vanille, würde ich sagen):

$stateProvider.state('dogs', { 
      url: '/ourdogsarecute_{specialIDofDog} 
     }). 
     state('dogs.specialDogState', { 
      url: '/specialinfo_{specialInfoOfDog}' 
     }); 

nun die folgende Situation entsteht: Im Backend (dh außerhalb von Angular), muss ich wandeln Sie einen Angular UI Router-Statuslink wie {stateName: 'dogs.specialDogState', stateParams: {specialIDofDog: 11212, specialInfoOfDog: 'likesbones' } } in eine gültige URL wie https://www.our-app.dog/ourdogsarecute_11212/specialinfo_likesbones um.

Ich habe keine Ahnung, wie man das ohne viel Handarbeit macht. Gibt es eine Art Parser für UI-Router-Zustände als Knotenmodul?

Ich kann auf den Front-End-Code zugreifen, wo die Statusdefinitionen irgendwie vom Backend liegen. Das ist nicht das Problem. Das Problem ist die Umwandlung von Statuslinks in URLs.

Antwort

1

UI-Router 1.0 teilen Sie den Code in UI-Router-Kern und UI-Router angularjs auf. Sie können den UI-Router-Core (der keine externen Abhängigkeiten hat) auf Ihrem Knoten-Backend verwenden, um diese URLs zu generieren. Da Sie Ihre Status bereits als JSON-Datei zur Verfügung haben, können Sie einfach die Zustände mit dem ui-router core in Ihrem Backend registrieren und dann mithilfe der Statusobjekte URLs generieren.

In Ihrem Knoten Backend, ui-Router Kern

npm install --save @uirouter/core

// The library exports most of its code 
var UIR = require('@uirouter/core'); 

// Create the router instance 
var router = new UIR.UIRouter(); 
// Get the state registry 
var registry = router.stateRegistry; 

var states = [ 
    { name: 'dogs', url: '/ourdogsarecute_{specialIDofDog}' }, 
    { name: 'dogs.specialDogState', url: '/specialinfo_{specialInfoOfDog}' }, 
]; 

states.forEach(state => registry.register(state)); 

var params = { specialIDofDog: '11212', specialInfoOfDog: 'lovesbones' }; 

// Get the internal state object 
var stateObj = registry.get('dogs.specialDogState').$$state(); 
// Generate the URL 
console.log(stateObj.url.format(params)); 
+0

Dank hinzuzufügen! Funktioniert. Aber ich denke, du meinst 'npm install --save @ uirouter/core' anstelle von' npm add --save @ uirouter/core'? – cis

+0

Ja, ich habe npm und Garnbefehle gemischt! –

0

Als Referenz: meine Lösung sieht jetzt so aus. Zunächst einmal, ich habe meine Zustandsdefinitionen in eine separate Datei setzen, so dass es einfacher ist es, von außen Zugriff auf:

var myStates = [ 
    { 
     name: 'dogs', stateProperties: { 
     url: '/ourdogsarecute_{specialIDofDog}' 
    } 
    }, { 
     name: 'dogs.specialDogState', stateProperties: { 
      url: '/specialinfo_{specialInfoOfDog}' 
     } 
    }]; 

Und dann in meinem app.config

for(var i = 0; i < myStates.length; i++) { 
      $stateProvider.state(myStates[i].name, myStates[i].stateProperties); 
     } 

Im Backend , ich habe diese Funktion erstellt:

/** 
    * @description Turns state name and state params into a URL string, using stateLinks definition synchronized from front end (being UI router state definitions) 
    * @param {string} stateName Something like 'dogs.info.specialAttributes' 
    * @param {object} stateParams Something like {dogID: 34346346, dogStatus: 'private', dogInfo: 'food'} 
    * @returns {string} URL 
    */ 
    stateLinkResolve: function(stateName, stateParams) { 

    if(!(stateName && stateName.length > 0)) { 
     return '/'; 
    } 

    var resultUrl = ''; 

    var splittedSubStates = stateName.split('.');// split "dogs.info.specialAttributes" into ["dogs","info","specialAttributes"] 

    var currentStateInHierarchy = ''; 
    for(var i = 0; i < splittedSubStates.length; i++) { 

     /* Add dot if "in between": not the first, not the last. So that "dogs" remains "dogs", but when going to "dogs.info", we want the dot in between */ 
     if(i > 0 && i < (splittedSubStates.length + 1)) { 
     currentStateInHierarchy += '.'; 
     } 
     currentStateInHierarchy += splittedSubStates[i]; // Add current splitted name (being only the last name part) to the state name in its context. I.e. when doing "info", we want to access "dogs.info" 
     var currState = _.find(stateDefs,{name: currentStateInHierarchy}); 
     var urlRaw = currState.stateProperties.url; 

     /* uiRouter URLs may contain wildcards for parameter values like /ourdogs_{dogID:int}_{dogStatus}/:dogInfo. 
     We go through each of these three types and replace them with their actual content. 
      */ 
     for(var currentParam in stateParams) { 
     urlRaw = urlRaw.replace(':' + currentParam, stateParams[currentParam]); // search for ":paramName" in URL 
     urlRaw = urlRaw.replace('{' + currentParam + '}', stateParams[currentParam]); // search for "{paramName}" in URL 

     // search for "{paramName:paramType}" in URL 
     var uiRouterParamTypes = ["hash", "string", "query", "path", "int", "bool", "date", "json", "any"]; 
     for(var j = 0; j < uiRouterParamTypes.length; j++) { 
      urlRaw = urlRaw.replace('{' + currentParam + ':' + uiRouterParamTypes[j] + '}', stateParams[currentParam]); 
     } 
     } 
     resultUrl += urlRaw; 
    } 
    return resultUrl; 
    } 

das Problem ist: Dies kann für die Rand Fällen fehlschlagen und es wird auf jeden Fall für die neuen Funktionen nicht zu UI Zustand Router implementiert ist und die Way-URLs werden dort erstellt. Also, immer noch auf eine Lösung hoffen, die direkt UI Router Magie verwendet.