0

I've built a small search app using AngularJS, UI Router and Elasticsearch. I have 2 templates that share 1 controller. Everything works correctly ... except for for when I try to implement query parameters.

The one template is a simple hp to enter search query or select from autocomplete (UI Bootstrap Typeahead). The other template is for search results and more searching (search box and area to display search results).

My states look like this:

.state('query', {//home
  url: '/',
  templateUrl: 'search/query.html',
  controller: 'searchCtrl as vm'
})
.state('search', {//results
  url: '/search?q',
  templateUrl: 'search/search.html',
  controller: 'searchCtrl as vm'
});

I'm using $state.go (in searchCtrl) from UI Router to transition between states.

vm.search = function() {
$state.go('search', {q: vm.searchTerms});
... 

What's happening is that after you enter your query/select autocomplete it goes to the 'search' state but I see this is in the url

http://localhost:8000/app/#/search?q=%5Bobject%20Object%5D

Then I have to enter the query again and the url changes to

http://localhost:8000/app/#/search?q=userinput

Finally I have to enter the query yet again for search to execute. Obviously I want all this to happen with ONE search submission. What am I doing wrong?

Any suggestions or ideas?

UPDATE I have this in a separate run.js file

.run(['$rootScope', '$state', '$stateParams', function($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;

UPDATE 2 I'm getting the same error whether I use my code or your code. It seems to be that when I go from 'state' to 'state', that searchTerms is being reset due to the way $scope works in Angular. I'm not sure how to resolve that yet because I'm not sure if the solution provided there will work with controllerAs syntax. Would it be wiser to just have an autocompleteCtrl for the hp/query page and have a queryService injected into each controller for searchTerms? Pls give a bit more time to fork the codepen, will send you comment when done.

Community
  • 1
  • 1
user3125823
  • 1,846
  • 2
  • 18
  • 46

2 Answers2

0

You should use a $stateParams as follows:

.state('search', {//results
    url: '/search/:q',
    templateUrl: 'search/search.html',
    controller: 'searchCtrl as vm'
});

Then in your controller you can inject $stateParams and access the value of that parameter with $stateParams.q.

Hope this helps.

Aibu
  • 401
  • 5
  • 10
0

Which version of Angular 1 are you using?

I have put together a very quick and crude codepen with what I think you are trying to achieve, let me know if this what you are after and if it helps at all.

$stateProvider
  .state('search', {
    url: '/',
    controller: 'myController as vm',
    template: '<div class="row"><form ng-submit="vm.query()"><div class="col-sm-10"><input class="form-control" ng-model="vm.search"></div><div class="col-sm-2">   <button class="btn btn-sm btn-default" ng-click="vm.query()">Search</button></div></form></div>'
  })
  .state('query', {
    url: '/query?q',
    controller: 'myController as vm',
    template: '<div class="row">Query: {{vm.search}}</div>'
  });

$urlRouterProvider.otherwise('/');

Update new CodePen - Working Pen

For some reason the order of Angular and UI Router had been changed.

mchaffe
  • 597
  • 1
  • 4
  • 14
  • I'm using 1.5, yes looks very similar to what I'm doing. Only difference are the 2 $stateProvider lines towards bottom. I have something similar in a separate file - Ill post an update to the question. – user3125823 Oct 17 '16 at 16:33
  • In the codepen I posted is that what you are trying to achieve? Why are you assigning the states and params to the rootScope? You can inject these in to the controller and access them when the controller is instantiated. – mchaffe Oct 17 '16 at 16:37
  • Is there any reason you cannot use the same process? Sorry just trying to figure out what it is you are trying to get from using the rootScope. – mchaffe Oct 17 '16 at 16:45
  • no prob, I used that code because it got thing working when I converted and started working with UI Router. I'll try the example you gave and put the $stateProvider lines after my $states. – user3125823 Oct 17 '16 at 16:48
  • Just updated the codepen to be more like your routes in your initial question - `http://codepen.io/mattchewone/pen/gwdEYL` – mchaffe Oct 17 '16 at 16:57
  • sorry, I thought it was fixed, but its still not working, I did some console.log logging, can you look at the UPDATE pls – user3125823 Oct 17 '16 at 17:52
  • Could you fork my codepen and alter it to match what you are doing so I could help a bit more? Not sure what you are doing with the `$rootScope`. – mchaffe Oct 17 '16 at 17:55
  • sorry about that, got pulled away from my desk for awhile there. When I converted my code to yours, I took out the $rootscope module and still got the same results :(. I think this has something so do with using 2 parent states and 1 controller(not sure if Angular was designed for that). If I end up getting it to work, I'll let you know and accept the answer. – user3125823 Oct 18 '16 at 18:44
  • Sorry not sure I follow. I have the same parent states as you with a single controller and I have it working how you have asked. If there is anything else I can do to help let me know. – mchaffe Oct 18 '16 at 20:32
  • As for your update it is wise to have controller per view, but given your request I had it working in the code pen, unless the code pen is not working for you? – mchaffe Oct 18 '16 at 20:35
  • no the code pen is not working for me. It looks exactly like what I'm looking for - so I'm glad its working for you, but I haven't been able to get it working. – user3125823 Oct 18 '16 at 20:37
  • @user3125823 I have just updated my answer, for some reason the pen had Angular and Angular UI Router in the wrong order, should be working now. – mchaffe Oct 18 '16 at 20:48
  • 1
    awesome, it works! I've accepted your answer - thanks for all your efforts! – user3125823 Oct 18 '16 at 20:51