3

I know we can use ng-change to solve this but I would like to understand why $watch doesn'twork on select. Maybe I'm doingsomething wrong but it seems I am not the only one to struggle with this. Here is my code:

HTML:

<div class="list">
        <label class="item item-input item-select">
            <div class="input-label">
                Serveur
            </div>
            <select ng-model="server" ng-options="s as s.label for s in serverschoice">
            </select>
        </label>
    </div>

JS:

.controller('SettingsCtrl', function ($scope, $log, serverSelection) {

    //List of servers to connect to
    $scope.serverschoice = serverSelection.servers;
    $scope.server = serverSelection.server;
    $scope.$watch('server', function(NewValue, OldValue) {
        serverSelection.server = NewValue;
        $scope.url = serverSelection.url;
    }, true);

})

.service("serverSelection", function() {
    var self = this;

    self.servers = [
        { label: 'Production', value: 1, url: 'url1' },
        { label: 'Training', value: 2, url: 'url2' },
        { label: 'Local', value: 3, url: 'url2' }
    ];

    self.server = self.servers[1];
    console.log(self.server);
    self.url = self.server.url;

})

Thanks...

curuba
  • 527
  • 1
  • 10
  • 29

2 Answers2

5

For make it working you need to do number of changes in your code, You need to put all server related information to one object named as self.serverInfo that will contain the information about server & servers directly bind this with scope variable will update binding automatically as per JavaScript Prototypal inheritance.

HTML

<body ng-controller="SettingsCtrl">
  <div class="list">
    <label class="item item-input item-select">
      <div class="input-label">
        Server
      </div>
      {{serverInfo}}
      <select ng-model="serverInfo.server" 
      ng-options="s as s.label for s in serverInfo.servers">
      </select>
    </label>
  </div>
</body>

Controller

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

app.controller('SettingsCtrl', function ($scope, $log, serverSelection) {

    //List of servers to connect to
    $scope.serverInfo= serverSelection.serverInfo;
    $scope.$watch('serverInfo.server', function(NewValue, OldValue) {
        $scope.url = $scope.serverInfo.server.url;
    }, true);

})

app.service("serverSelection", function() {
    var self = this;
    self.serverInfo = {};
    self.serverInfo.servers = [
        { label: 'Production', value: 1, url: 'url1' },
        { label: 'Training', value: 2, url: 'url2' },
        { label: 'Local', value: 3, url: 'url2' }
    ];

    self.serverInfo.server = self.serverInfo.servers[1];
    console.log(self.server);
    self.serverInfo.url = self.serverInfo.server.url;

})

Working Plunkr

Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
  • Should ServerSelection service return somthing then, no? – curuba May 02 '15 at 16:21
  • @curuba thats my bad you need to put watch on `'serverSelection.server'` – Pankaj Parkar May 02 '15 at 16:23
  • Hmm this doesn't work. It seems that the HTML part can't access serverSelection service if it is just injected in the controller but not assigned to a variable within the $scope. – curuba May 02 '15 at 16:38
  • @curuba now look at my updated code & plunkr..all is working..I'll update description of answer..in a while – Pankaj Parkar May 02 '15 at 16:39
  • 1
    Sorry I had missed your ligne : $scope.serverSelection= serverSelection; Now it is triggering the $watch, my serverSelection.server is updated but not my serverSelection.url. I think I need to create a method within my service that I'll call from the $watch. – curuba May 02 '15 at 16:45
  • @curuba plunkr has been already updated..you can check the console..which is firing watch correctly.. – Pankaj Parkar May 02 '15 at 16:47
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/76774/discussion-between-pankajparkar-and-curuba). – Pankaj Parkar May 02 '15 at 16:48
  • This problem was presenting itself to me as an extra call to the $watch handler with a null value as the select was being unloaded. Changing the options to use `ng-option` instead of building option elements with `ng-repeat` fixed it for me. – Gangstead Oct 31 '18 at 18:28
1

I accept answer from @pankajparkar but I'd like to show my final code as in fact with the proper binding proposed by @pankajparkar I don't need a $watch anymore.

HTML

    <div class="list">
        <label class="item item-input item-select">
            <div class="input-label">
                Serveur
            </div>
            <select ng-model="serverSelection.server" ng-options="s as s.label for s in serverSelection.servers">
            </select>
        </label>
    </div>
    <p>URL: {{serverSelection.server.url}}</p>

JS

.controller('SettingsCtrl', function ($scope, $log, serverSelection) {

    //List of servers to connect to
    $scope.serverSelection= serverSelection;

})


.service("serverSelection", function() {
    var self = this;

    self.servers = [
        { label: 'Production', value: 1, url: 'url0' },
        { label: 'Training', value: 2, url: 'url1' },
        { label: 'Local', value: 3, url: 'url2' }
    ];

    self.server = self.servers[1];

})
curuba
  • 527
  • 1
  • 10
  • 29