Dynamic parameters with angular ui router

回眸只為那壹抹淺笑 提交于 2019-12-10 22:07:04

问题


I am wondering how to include parameters when changing state and sending the request to get the template from the backend.

Here is my app:

angular.module('questionnaireApp', ['ngAnimate', 'ui.router', 'ui.bootstrap'])

.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {

$stateProvider

  .state('questionnaire', {
   url: '/questionnaire',
   templateUrl: 'questionnaire/questionnaire.html',
   controller: 'questionnaireCtrl'
  })

  .state('questionnaire.receiver_name', {
    url: '/receiver_name',
    templateUrl: 'questionnaire/receiver_name.html'
  })

  .state('questionnaire.location', {
    url: '/location',
    templateUrl: 'questionnaire/location.html'
  })

  .state('poem', {
    url: '/poem',
    templateUrl: 'questionnaire/poem.html',
    controller: 'questionnaireCtrl'
  });

$urlRouterProvider.otherwise('/questionnaire/receiver_name');
}])

.controller('questionnaireCtrl', ['$scope', '$http', '$state', function($scope, $http, $state) {

  $scope.formData = {};
}]);

I am saving user input in $scope.formData. I need to include it in my request to be able to render questionnaire/poem.html.

Something like:

.state('poem', {
  url: '/poem',
  templateUrl: 'questionnaire/poem' + $scope.formData + '.html',
  controller: 'questionnaireCtrl'
});

How can I do that?

Or is there any variant that can help me send the formData to my backend so that it can render the poem.html page properly?


回答1:


You can do it by making the templateUrl a function. Take a look at this example, taken from ui-router documentation ( https://github.com/angular-ui/ui-router/wiki ):

$stateProvider.state('contacts', {
  templateUrl: function ($stateParams){
      return '/partials/contacts.' + $stateParams.filterBy + '.html';
  }
})

In the above example, we get $stateParams as an argument (note, it's not an injection, more details on the doc site) and use the parameter "filterBy" as part of the template url. In your case, it's formData.

Note 1: You must pass a string. If formData is an object, you can't use it as part of the templateUrl, and you probably won't be able to even pass it as part of the stateParams. maybe you want a specific field from it? Something like 'formType'?

Note 2: As mb21 mentioned, all of this has nothing to do with the backend. if you want to send the form data, do a REST call. Routing should involve only the client side.




回答2:


questionnaire/poem.html should be an Angular html template file, nothing dynamically generated by the server.

To save your data, use Angular's http service to do a post request to the server that wants the data.

If you have the data on PageA with ControllerA and need to have it on PageQ with ControllerQ, you should share the data using a factory between the two controllers. No need to involve the server.




回答3:


I finally managed to achieve my goal: retrieve the poem with one HTTP request only.

To do that:

  • I store the HTML templates inside the Angular app so that it only needs to retrieve JSON data
  • form data is sent with regular http post
  • poem data is sent back in JSON format
  • the poem is displayed thanks to Angular data binding

Angular code:

angular.module('thePoetApp').config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {

$stateProvider

// route to show our basic form (/questionnaire)
.state('questionnaire', {
  url: '/questionnaire',
  templateUrl: 'questionnaire/questionnaire.html',
})

// nested states
// each of these sections will have their own view
// url will be nested (/questionnaire/receiver_name)
.state('questionnaire.receiver_name', {
  url: '/receiver_name',
  template: '<div class="col-md-3 text-left ng-scope"></div><div class="form-container col-md-6 text-center ng-scope"><div class="form-group"><label for="receiver_name">Receiver Name:</label><input name="receiver_name" ng-model="formData.receiver_name" receiver_name="receiver_name" required="" type="text" class="ng-pristine ng-invalid ng-invalid-required"></div><div class="form-group"><label for="receiver_sex">Receiver Sex:</label><input name="receiver_sex" ng-model="formData.receiver_sex" receiver_sex="receiver_sex" required="" type="radio" value="male" class="ng-pristine ng-invalid ng-invalid-required">Male<input name="receiver_sex" ng-model="formData.receiver_sex" receiver_sex="receiver_sex" required="" type="radio" value="female" class="ng-pristine ng-invalid ng-invalid-required">Female</div></div><div class="col-md-3 text-right ng-scope"><a class="btn btn-primary" ui-sref="questionnaire.location">Next Step</a></div>',
})

// url will be /questionnaire/location
.state('questionnaire.location', {
  url: '/location',
  template: '<div class="col-md-3 text-left ng-scope"><a class="btn btn-primary" ui-sref="questionnaire.receiver_name">Previous Step</a></div><div class="form-container col-md-6 text-center ng-scope"><div class="form-group"><label for="location">Location:</label><input location="location" name="location" ng-model="formData.location" required="" type="text" class="ng-pristine ng-invalid ng-invalid-required"></div></div><div class="col-md-3 text-right ng-scope"><a class="btn btn-primary" ui-sref="questionnaire.relationship">Next Step</a></div>'
})

// url will be /questionnaire/relationship
.state('questionnaire.relationship', {
  url: '/relationship',
  template: '<div class="col-md-3 text-left ng-scope"><a class="btn btn-primary" ui-sref="questionnaire.location">Previous Step</a></div><div class="form-container col-md-6 text-center ng-scope"><div class="form-group ng-scope" ng-controller="RelationshipsTypeaheadCtrl"><label for="relationship">Relationship:</label><input autocomplete="off" name="relationship" ng-model="formData.relationship" relationship="relationship" required="" type="text" typeahead-editable="false" typeahead="suggestion for suggestion in relationships($viewValue)" class="ng-pristine ng-invalid ng-invalid-required"><ul class="dropdown-menu ng-isolate-scope"><!-- ngRepeat: match in matches --></ul></div></div><div class="col-md-3 text-right ng-scope"><a class="btn btn-primary" ui-sref="questionnaire.trait">Next Step</a></div>'
})

// url will be /questionnaire/trait
.state('questionnaire.trait', {
  url: '/trait',
  template: '<div class="col-md-3 text-left ng-scope"><a class="btn btn-primary" ui-sref="questionnaire.relationship">Previous Step</a></div><div class="form-container col-md-6 text-center ng-scope"><div class="form-group ng-scope" ng-controller="TraitsTypeaheadCtrl"><label for="trait">Trait:</label><input autocomplete="off" name="trait" ng-model="formData.trait" trait="trait" required="" type="text" typeahead-editable="false" typeahead="suggestion for suggestion in traits($viewValue)" class="ng-pristine ng-invalid ng-invalid-required"><ul class="dropdown-menu ng-isolate-scope"><!-- ngRepeat: match in matches --></ul></div></div><div class="col-md-3 text-right ng-scope"><a class="btn btn-primary" ui-sref="questionnaire.message">Next Step</a></div>'
})

// url will be /questionnaire/message
.state('questionnaire.message', {
  url: '/message',
  template: '<div class="col-md-3 text-left ng-scope"><a class="btn btn-primary" ui-sref="questionnaire.trait">Previous Step</a></div><div class="form-container col-md-6 text-center ng-scope"><div class="form-group ng-scope" ng-controller="MessagesTypeaheadCtrl"><label for="message">Message:</label><input autocomplete="off" name="message" ng-model="formData.message" message="message" required="" type="text" typeahead-editable="false" typeahead="suggestion for suggestion in messages($viewValue)" class="ng-pristine ng-invalid ng-invalid-required"><ul class="dropdown-menu ng-isolate-scope"><!-- ngRepeat: match in matches --></ul></div></div>'
})

.state('poem', {
  url: '/poem',
  template: '<div class="poem"><p>{{ poem.title }}</p><p><div>{{ poem.intro_verse.line_one}}</div><div>{{ poem.intro_verse.line_two}}</div><div>{{ poem.intro_verse.line_three}}</div><div>{{ poem.intro_verse.line_four}}</div><div>{{ poem.intro_verse.line_five}}</div></p><p><div>{{ poem.trait_verse.line_one}}</div><div>{{ poem.trait_verse.line_two}}</div><div>{{ poem.trait_verse.line_three}}</div><div>{{ poem.trait_verse.line_four}}</div><div>{{ poem.trait_verse.line_five}}</div></p><p><div>{{ poem.message_verse.line_one}}</div><div>{{ poem.message_verse.line_two}}</div><div>{{ poem.message_verse.line_three}}</div><div>{{ poem.message_verse.line_four}}</div><div>{{ poem.message_verse.line_five}}</div></p><div class="text-center"><a class="btn btn-warning" ui-sref="questionnaire.receiver_name">Restart</a></div></div>'
});

// catch all route
// send users to the receiver_name page
$urlRouterProvider.otherwise('/questionnaire/receiver_name');

Angular controller:

postParams =
{"questionnaire":
  {
   "receiver_name": $scope.formData.receiver_name,
   "receiver_sex": $scope.formData.receiver_sex,
   "location": $scope.formData.location,
   "relationship": $scope.formData.relationship,
   "trait_category": $scope.formData.trait,
   "message_category": $scope.formData.message
  }
}
 // send post request
$http({
  method  : 'POST',
  url     : 'api/questionnaire/poem',
  data    : $.param(postParams),  // pass in data as strings
  headers : { 'Content-Type': 'application/x-www-form-urlencoded' }  // set the headers so angular passing info as form data (not request payload)
})
.success(function(data) {
    if (data.success) {
      $scope.poem = data.poem;
      $scope.formData = {};
      $state.go('poem');
    }
});

$scope.poem = data.poem' sets the poem data so that {{ poem.title }} and so on get replaced when going to the poem state.



来源:https://stackoverflow.com/questions/24588086/dynamic-parameters-with-angular-ui-router

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!