0
votes

I'm trying to set up a complex URL structure:

http://example.com/quote/:param1/:param2/:param3/:param4

Each state uses the same template except for 1.

My question being, is there a way to dynamically pass each parameter to the next state without having multiple templates? or do I need to set up individual templates and change only the ui-sref

Here are my states:

.state('quote', {
    url: '/quote',
    ...
})

.state('quote.policy', {
    url: '/',
    templateUrl: 'partials/quote/quote.select.html',
    page: {next: 'location'}
    ...
})

.state('quote.location', {
    url: '/:policy',
    templateUrl: 'partials/quote/quote.select.html',
    page: {next: 'age'}
    ...
})

.state('quote.age', {
    url: '/:policy/:state',
    templateUrl: 'partials/quote/quote.select.html',
    page: {next: 'income'}
    ...
})

.state('quote.income', {
    url: '/:policy/:state/:age',
    templateUrl: 'partials/quote/quote.income-select.html',
    page: {next: 'priority'}
    ...
})

.state('quote.priority', {
    url: '/:policy/:state/:age/:income',
    templateUrl: 'partials/quote/quote.select.html',
    ... 
})

Each param is collected with a child state of quote. They all use the same template:

snippet from partials/quote/quote.select.html

<label 
    ng-repeat="option in options[page.type]"
    ui-sref="quote.{{page.next}}({ page.type : option.value })" 
    ng-click="formData.selections[page.type] = option.value">

Another issue I'm having is that the current ui-sref doesn't pass the value to the URL, i.e. doesn't append the new value.

1
shouldnt the states be children of one another? ie. quote.income should be quote.policy.location.age.income? - haxxxton
Ah... That's a very valid point! Sorry, I'm new to Angular so still learning the ropes. When I've resolved it in my own code I will update the question with a solution. - harelpls

1 Answers

0
votes

OK, for anyone who has a similar problem, I figured it out myself. There were a few things I was doing wrong. This is refactored too.

Firstly, the ui-sref (oddly) needs the property to be an expression:

<label ui-sref="{{ page.next }}({ {{ page.type }} : option.value })">

which I guess makes sense as you can't use variables in place of a property without obj[prop] syntax.

Contrary to haxxxton's advice on nesting the states one after the other, I stuck to them being only one level down, i.e. quote.policy, quote.age, etc. Here is an example of the deepest state I used:

.state('quote.show', {
    url: '/:policy/:state/:age/:income/:priority/:i',
    templateUrl: '/partials/quote/quote.show.html',
    controller: 'QuoteController'
})

Note the URL.

To get this working, I scratched my head for a bit. I had to pass every past selected parameter to the next state, which isn't straightforward as the states aren't aware of other states' params.

$stateChangeStart came to the rescue (in parent state controller):

$scope.$on('$stateChangeStart', 
function(event, toState, toParams, fromState, fromParams){
    _.each(fromParams, function(val, key){
        toParams[key] = val;
    })
});

Since both the previous state's params and the params being pushed to the next state are available in this event, I was able to add to the parameters each time. Awesome! Unfortunately the underscore each method was necessary to get the key - if there is a better way of doing this, please let me know!

This lets me achieve this working URL: http://example.com/#!/quote/Sgl/NSW/31-37/tier3/all/

It is of course easy to add in the keywords for each stage to the URL i.e. http://example.com/quote/policy/Sgl/state/VIC... by reflecting it in the URL of the state definition, but we don't want this approach.

GO ANGULAR!!