Patrick
Patrick

Reputation: 13974

getting the ng-object selected with ng-change

Given the following select element

<select ng-options="size.code as size.name for size in sizes " 
        ng-model="item.size.code" 
        ng-change="update(MAGIC_THING)">
</select>

Is there a way to get MAGIC_THING to be equal to the currently selected size, so I have access to size.name and size.code in my controller?

size.code affects a lot of the other parts of the app (image urls, etc), but when the ng-model of item.size.code is updated, item.size.name needs to be updated as well for the user facing stuff. I assume that the correct way to do this is capturing the change event and setting the values inside of my controller, but I'm not sure what I can pass into update to get the proper values.

If this is completely the wrong way to go about it, I'd love to know the right way.

Upvotes: 322

Views: 737867

Answers (10)

DolceVita
DolceVita

Reputation: 2100

you also coud try this:

<select  ng-model="selectedItem" ng-change="update()">
   <option ng-repeat="item in items" 
         ng-selected="selectedItem == item.Id" value="{{item.Id}}">
      {{item.Name}}
   </option>
</select>

Upvotes: 16

Sagi
Sagi

Reputation: 1009

This is the cleanest way to get a value from an angular select options list (other than The Id or Text). Assuming you have a Product Select like this on your page :

<select ng-model="data.ProductId"
        ng-options="product.Id as product.Name for product in productsList"
        ng-change="onSelectChange()">
</select>

Then in Your Controller set the callback function like so:

    $scope.onSelectChange = function () {
        var filteredData = $scope.productsList.filter(function (response) {
            return response.Id === $scope.data.ProductId;
        })
        console.log(filteredData[0].ProductColor);
    }

Simply Explained: Since the ng-change event does not recognize the option items in the select, we are using the ngModel to filter out the selected Item from the options list loaded in the controller.

Furthermore, since the event is fired before the ngModel is really updated, you might get undesirable results, So a better way would be to add a timeout :

        $scope.onSelectChange = function () {
            $timeout(function () {
            var filteredData = $scope.productsList.filter(function (response) {
                return response.Id === $scope.data.ProductId;
            })
            console.log(filteredData[0].ProductColor);
            }, 100);
        };

Upvotes: 1

Aakash
Aakash

Reputation: 23835

AngularJS's Filter worked out for me.

Assuming the code/id is unique, we can filter out that particular object with AngularJS's filter and work with the selected objects properties. Considering the example above:

<select ng-options="size.code as size.name for size in sizes" 
        ng-model="item.size.code" 
        ng-change="update(MAGIC_THING); search.code = item.size.code">
</select>

<!-- OUTSIDE THE SELECT BOX -->

<h1 ng-repeat="size in sizes | filter:search:true"
    ng-init="search.code = item.size.code">
  {{size.name}}
</h1>

Now, there are 3 important aspects to this:

  1. ng-init="search.code = item.size.code" - on initializing h1 element outside select box, set the filter query to the selected option.

  2. ng-change="update(MAGIC_THING); search.code = item.size.code" - when you change the select input, we'll run one more line which will set the "search" query to the currently selected item.size.code.

  3. filter:search:true - Pass true to filter to enable strict matching.

That's it. If the size.code is uniqueID, we'll have only one h1 element with the text of size.name.

I've tested this in my project and it works.

Good Luck

Upvotes: 1

dworrad
dworrad

Reputation: 719

You need to use "track by" so that the objects can be compared correctly. Otherwise Angular will use the native js way of comparing objects.

So your example code would change to -

    <select ng-options="size.code as size.name
 for size in sizes track by size.code" 
ng-model="item.size.code"></select>

Upvotes: 1

barış &#231;ıracı
barış &#231;ıracı

Reputation: 1043

//Javascript
$scope.update = function () {
    $scope.myItem;
    alert('Hello');
}
<!--HTML-->
<div class="form-group">
     <select name="name"
             id="id" 
             ng-model="myItem" 
             ng-options="size as size.name for size in sizes"
             class="form-control" 
             ng-change="update()"
             multiple
             required>
     </select>
</div>

İf you want to write, name, id, class, multiple, required , You can write in this way.

Upvotes: 2

Divyesh Rupawala
Divyesh Rupawala

Reputation: 1221

You can also directly get selected value using following code

 <select ng-options='t.name for t in templates'
                  ng-change='selectedTemplate(t.url)'></select>

script.js

 $scope.selectedTemplate = function(pTemplate) {
    //Your logic
    alert('Template Url is : '+pTemplate);
}

Upvotes: 47

Mark Rajcok
Mark Rajcok

Reputation: 364727

Instead of setting the ng-model to item.size.code, how about setting it to size:

<select ng-options="size as size.name for size in sizes" 
   ng-model="item" ng-change="update()"></select>

Then in your update() method, $scope.item will be set to the currently selected item.

And whatever code needed item.size.code, can get that property via $scope.item.code.

Fiddle.

Update based on more info in comments:

Use some other $scope property for your select ng-model then:

<select ng-options="size as size.name for size in sizes" 
   ng-model="selectedItem" ng-change="update()"></select>

Controller:

$scope.update = function() {
   $scope.item.size.code = $scope.selectedItem.code
   // use $scope.selectedItem.code and $scope.selectedItem.name here
   // for other stuff ...
}

Upvotes: 504

Northstrider
Northstrider

Reputation: 1159

This might give you some ideas

.NET C# View Model

public class DepartmentViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
}

.NET C# Web Api Controller

public class DepartmentController : BaseApiController
{
    [HttpGet]
    public HttpResponseMessage Get()
    {
        var sms = Ctx.Departments;

        var vms = new List<DepartmentViewModel>();

        foreach (var sm in sms)
        {
            var vm = new DepartmentViewModel()
            {
                Id = sm.Id,
                Name = sm.DepartmentName
            };
            vms.Add(vm);
        }

        return Request.CreateResponse(HttpStatusCode.OK, vms);
    }

}

Angular Controller:

$http.get('/api/department').then(
    function (response) {
        $scope.departments = response.data;
    },
    function (response) {
        toaster.pop('error', "Error", "An unexpected error occurred.");
    }
);

$http.get('/api/getTravelerInformation', { params: { id: $routeParams.userKey } }).then(
   function (response) {
       $scope.request = response.data;
       $scope.travelerDepartment = underscoreService.findWhere($scope.departments, { Id: $scope.request.TravelerDepartmentId });
   },
    function (response) {
        toaster.pop('error', "Error", "An unexpected error occurred.");
    }
);

Angular Template:

<div class="form-group">
    <label>Department</label>
    <div class="left-inner-addon">
        <i class="glyphicon glyphicon-hand-up"></i>
        <select ng-model="travelerDepartment"
                ng-options="department.Name for department in departments track by department.Id"
                ng-init="request.TravelerDepartmentId = travelerDepartment.Id"
                ng-change="request.TravelerDepartmentId = travelerDepartment.Id"
                class="form-control">
            <option value=""></option>
        </select>
    </div>
</div>

Upvotes: 1

jmbmage
jmbmage

Reputation: 2547

If Divyesh Rupawala's answer doesn't work (passing the current item as the parameter), then please see the onChanged() function in this Plunker. It's using this:

http://plnkr.co/edit/B5TDQJ

Upvotes: 8

Jignesh Variya
Jignesh Variya

Reputation: 1919

<select ng-model="item.size.code">
<option ng-repeat="size in sizes" ng-attr-value="size.code">{{size.name}}          </option>
</select>

Upvotes: 2

Related Questions