0

I wrote a little program using ui-select in angular and it seems that they some "bugs" with the ng model (for me, it have some "strange" behavior) and I couldn't bind the value set in the ng-model from the .js controller.

Here is my html code :

<body ng-controller="mainController">
<p>SelectedName: {{test.selectedContract.name}}</p>
<p>Selected: {{test.selectedContract}}</p>

<ui-select ng-model="test.selectedContract">
  <ui-select-match>
    {{$select.selected.name}} - {{$select.selected.value}}    
</ui-select-match>

<ui-select-choices repeat="contract in (contracts | filter: {name: $select.search} ) track by contract.name">
    {{contract.name}} - {{contract.value}}    
</ui-select-choices>
</ui-select>

<p> selectedFromJS = {{mySelected}} </p>
<p> selectedNameFromJS = {{mySelected2}} </p> 

The two variables Selected and SelectedName seems correct and I could view the selectecContract in html by if I wanted to manipulate it in my controller, I failed.

Here is the binding in my controller :

$scope.test = {};
$scope.test.selectedContract = {};

$scope.mySelected = $scope.test.selectedContract
$scope.mySelected2 = $scope.test.selectedContract.name

Finally, here is my code : http://plnkr.co/edit/WxMXD8yptwfsr80hJJWJ?p=preview

As you can see, the last two variables selectedFromJS and selectedNameFromJS didn't work and didn't show anything.

Can you please show me how can I do correctly the binding and how can I manipulate the selected item in my controller.

Thanks !

3 Answers 3

1

The controller is loaded once. Data is bing to test.selectedContract. This is how you create your own watches. $watch service helps you to run some code when some value attached to the $scope has changed.

Please Try:

  $scope.$watch('test.selectedContract', function() {
       $scope.mySelected = $scope.test.selectedContract
       $scope.mySelected2 = $scope.test.selectedContract.name
  });
1
  • thanks, it works, i think that $watch is the best solution here Commented Nov 26, 2016 at 20:57
0

You solve your problem by using $watch:

If you want to be notified whenever $digest is called, you can register a watchExpression function with no listener. (Be prepared for multiple calls to your watchExpression because it will execute multiple times in a single $digest cycle if a change is detected.)

So, you need to implement a watchExpression for the variable test.selectedContract, like this:

$scope.$watch('test.selectedContract', function(newVal, oldVal){
   $scope.mySelected = newVal
   $scope.mySelected2 = newVal.name;
});

Here isa plunkr with a watchExpression implemented: http://plnkr.co/edit/6Z6Xes02C42bojHfDlnl?p=preview

If you want to know more abou the $digest cycle and $watch expressions, take a look at the first two answers in this question: How do I use $scope.$watch and $scope.$apply in AngularJS?

0

It works exactly as expected.

Here in the controller you assign to the mySelected and mySelected2 a values not references to the object so the binding you think of doesn't exist,

$scope.mySelected = $scope.test.selectedContract
$scope.mySelected2 = $scope.test.selectedContract.name

you can make it work in multiple ways


1 with function

JS

$scope.mySelected = function(){
  $scope.test.selectedContract;
}

HTML

<p> selectedFromJS = {{mySelected()}} </p>

2 assign reference

JS

$scope.mySelected2 = $scope.test

HTML

<p> selectedNameFromJS = {{mySelected2.selectedContract.name}} </p>

here in the case of reference, the mySelected2 is a reference to test since it's very simple object


3 using ui-select on-select event

JS

$scope.updateMySelect = function(){
  $scope.mySelected = $scope.test.selectedContract;
  $scope.mySelected2 = $scope.test.selectedContract.name
}

HTML

<ui-select ng-model="test.selectedContract" on-select="updateMySelect()">

Not the answer you're looking for? Browse other questions tagged or ask your own question.