1

I am working on a project that will ultimately be responsive and the navigation will collapse down to a select control, so I found an article on Google about this. I learned that the ng-change does not fire an angular event but it was suggested that adding a ng-click to the option tags would replace that void.

As I built my POC, the first thing I realized is that my copying-and-pasting the go function into each meant the design wasn't DRY (so alarms began sounding off in my head) and probably means this is not the right way to do this.

I continue to build what I understood from the article and it doesn't change the routes.

I built a plunker.

Here's the HTML:

<!DOCTYPE html>
<html ng-app="myApp">

  <head>
    <meta charset="utf-8" />
    <title>Proof of Concept</title>
    <link data-require="bootstrap-css@*" data-semver="3.1.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
  </head>

  <body>
    <form>
      <select name="naver" id="naver">
        <option value="home" ng-click="go('/')">Home</option>
        <option value="first" ng-click="go('/first')">First</option>
        <option value="second" ng-click="go('/second')">Second</option>
      </select>
    </form>
    <div ng-view=""></div>
    <script data-require="[email protected]" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js" data-semver="1.2.16"></script>
    <script data-require="angular-route@*" data-semver="1.2.14" src="http://code.angularjs.org/1.2.14/angular-route.js"></script>
    <script data-require="jquery@*" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
    <script data-require="bootstrap@*" data-semver="3.1.1" src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
    <script src="app.js"></script>
  </body>

</html>

and the script:

var app = angular.module("myApp", ['ngRoute']);

app.config(function($routeProvider){
    $routeProvider
        .when('/', {
            templateUrl: "home.html",
            controller: 'HomeController'
        })
        .when('/first', {
            templateUrl: "first.html",
            controller: 'FirstController'
        })
        .when('/second', {
            templateUrl: "second.html",
            controller: 'SecondController'
        })
        .otherwise({ redirectTo: '/' });
});

app.controller('HomeController', function($scope, $location){
    $scope.go = function( path ){
        $location.path(path);
    }
});
app.controller('FirstController', function($scope, $location){
    $scope.go = function( path ){
        $location.path(path);
    }
});
app.controller('SecondController', function($scope, $location){
    $scope.go = function( path ){
        $location.path(path);
    }
});

Any help is greatly appreciated!

3 Answers 3

8

You indeed can be more DRY than that. I would:

  1. Remove all go() functions from the views' controllers.

  2. Create a new controller (e.g. NavCtrl) for the navigation "bar".

    <form ng-controller="NavCtrl">
    
  3. Remove the ngClick directives from the <option> elements (since they don't seem to have any effect - at least in Chrome).

  4. Add an ngModel to the <select> element to keep track of the selected page/view.

  5. Add an ngChange listener to the <select> element to trigger a "redirection" every time the selected page/view changes.

    <select id="naver" name="naver" ng-model="currentPage" ng-change="go(currentPage)">
      <option value="home">Home</option>
      <option value="first">First</option>
      <option value="second">Second</option>
    </select>
    
  6. Define the go() function inside the aforementioned NavCtrl controller.

    app.controller('NavCtrl', function NavCtrl($location, $scope) {
      $scope.currentPage = 'home';
      $scope.go = function go(page) {
        $location.path('/' + page);
      };
    });
    

See, also, this short demo.

Sign up to request clarification or add additional context in comments.

1 Comment

I wish YOU had written the article that I read since I understood exactly what you meant the first time. Thanks!
1

The go() function cannot be called, since the select control is out of the scope of the page controllers.

Try this instead:

plunkr

1 Comment

Scope is going to KILL me as I try to learn Angular. Thanks for the help.
0

To Complement the above answers, i have created a directive which will switch routes based on the value selected.

please find the plunk here: plunkr

Here is the code:

  `app.controller('mainController', function($rootScope, $scope) {
  $scope.testArray = [{
    'option': 'home'
  }, {
    'option': 'first'
  }];
  $scope.testModel = $scope.testArray[0].option;
});

app.directive('selectDirective', function() {
  return {
    scope: {
      testModel: '=',
      testArray: '=',
      go: '&'
    },
    require: 'ngModel',
    template: `<select name="testModel" ng-model="testModel" value="option.option" ng-change="Model(testModel)" ng-options="option.option for option in testArray">{{option.option}}</option> 
               <option value="" selected="selected">Select an Item</option>
                </select>`,
    replace: true,
    controller: function($scope, $location) {
      $scope.Model = function(page) {
        $location.path('/' + page.option);
      }
    }
  }
});`

HTML:

'<test-directive dat-options="testArray" dat-heldmodel="testModel"></test-directive>
    <div>Selected: {{testModel}}</div>'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.