2

How to show option.Brand.Name as the title of the select field without using java script and changing the ng-model?

<select ng-model="detail.BrandId" title="" class="form-control" disabled>
    <option ng-repeat="option in mainCtrl.products" ng-selected="option.Id === detail.ProductId" ng-value="option.BrandId">{{option.Brand.Name}}</option>
</select>
Len
  • 534
  • 1
  • 15
  • 31
  • @Shaheryar.Akram Thanks for the suggestion but it didn't work on my end. – Len Jan 31 '19 at 00:48
  • just use ng-attr-title="{{detail. Brand.Name}}" – Mina paulis Feb 06 '19 at 06:35
  • @minaalfy Thanks for the suggestion but I don't want to change the ng-model to 'detail.Brand' – Len Feb 07 '19 at 05:58
  • Exactly why are you trying to accomplish this? This sounds like poor design more than anything. – MattE Feb 08 '19 at 00:37
  • The select field above is one of the many fields in a table due to the space, user would not be able to view the 'Brand.Name' right away and they would need to refresh to be able to view it by tooltip – Len Feb 08 '19 at 01:09
  • Can you please provide records of `mainCtrl.products` ? – rahim.nagori Feb 08 '19 at 06:11

6 Answers6

1

You can register the selected option object in the ng-repeat parent scope by using as alias-expression provided by ng-repeat. In your case you just need to do something like that:

<select ng-model="detail.BrandId" 
        title="{{options | selectedProductFilter : detail.ProductId}}" 
        class="form-control" 
        disabled>
    <option ng-repeat="option in mainCtrl.products as options" 
            ng-selected="option.Id === detail.ProductId" 
            ng-value="option.BrandId">
        {{option.Brand.Name}}
    </option>
</select>

The options object will be available in your controller closure and you can display the title by using a custom filter.

angular.module("app").filter('selectedProductFilter',
    function () {
        return function (input, id) {
            if (!input) return "";
            let occurence = input.filter(function (x) {
                return x.Id == id;
            });
            return occurence.length > 0 ? occurence[0].Brand.Name: "";
        }
    }
);
Len
  • 534
  • 1
  • 15
  • 31
voodoo_patch
  • 472
  • 4
  • 16
  • 1
    Thanks for your suggestion but 'selectedOption' would contain all of 'mainCtrl.products' not just the selected option. – Len Feb 08 '19 at 01:03
  • You're right. Check out the filter usage. It's pretty clean in the view. – voodoo_patch Feb 08 '19 at 07:28
  • Thanks I never thought of using filters like this but it seems pretty heavy for just displaying the title. I'll consider using this though if I don't find a solution. Thanks again. – Len Feb 08 '19 at 10:32
1

AngularJS and select-options

Try using ng-options AngularJS ngOptions directive within select element itself. Then you don't need to add each option element yourself using ng-repeat.

Clarification

The title-attribute belongs to the select-element and will show if you hover over the select. You would like the title to reveal the current selected option? Did I understand you correctly?

How to show option.Brand.Name as the title of the select field

Curious, where this detail.ProductId comes from? Is the brand preselected by product-id (see your code)?

ng-selected="option.Id === detail.ProductId"

Solution space

Your requirements/restrictions are:

  • without using JavaScript (maybe because you can't change the sources)
  • without changing the ng-model (because you need there only the BrandId for some database-reasons)

So since the title of the select-element has no access to the options inside, the only way to set it is depending on the current selection, i.e. your detail.BrandId. So the title can only set dynamically (depending on the current selection) by using standard-angularJS means, as:

Expected behavior

The only scope-variable changed by selecting is specified within select's ng-model as detail.BrandId. This will be set when user selects an option to its property BrandId. When user selects between options they will be visible with ther BrandName as label. After selection this BrandName (label of the option) should be shown as title of the entire select element.

So we need to get from detail.BrandId (selected ng-model) to related options BrandName (as this should show as title).

Possible Solution

Only way is to use standard angular expressions/filters/array-indexing to get the whole option by the selected detail.BrandId (ng-model)

Then we can lookup the option.BrandName by this equation after selected detail.BrandId === option.BrandId

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

app.controller('mainCtrl', function($scope){
  $scope.products = [
    {Id: 0, name: 'Watson', brandId: 1, brandName:"IBM"},
    {Id: 1, name: 'DB2', brandId: 1, brandName:"IBM"},
    {Id: 2, name: 'Windows', brandId: 2, brandName: "Microsoft"},
    {Id: 3, name: 'Office', brandId: 2, brandName: "Microsoft"}
  ];
  $scope.detail = { ProductId: 3, BrandId: null };
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>

<!DOCTYPE html>
<html>
  <body data-ng-app="app" data-ng-controller="mainCtrl">
      <table border="1">
        <tr>
   <th>Product Id</th><th>Product Name</th><th>Choose Brand</th><th>Brand Id</th>
        </tr>
        <tr>
          <td>{{detail.ProductId}}</td>
          <td>{{ (products | filter: {Id: detail.ProductId})[0].name }}</td>
          <td>
            <select class="form-control"
             ng-model="detail.BrandId" 
             ng-init="detail.BrandId = (products | filter: {Id: detail.ProductId})[0].brandId"
             ng-options="o.brandId as ('['+ o.Id +'] '+ o.name +' : '+ o.brandName  +' ('+ o.brandId +')') for o in products"
             title="{{ (products | filter: {brandId: detail.BrandId})[0].brandName}}"
            >
              <!-- default option when not preset by detail.ProductId-->
              <option value="">-- please choose brand --</option>
            </select>
        </td>
        <td>{{detail.BrandId}}</td>
      </tr>
    </table>

    <hr/>
      <p>Product is predefined. So the brand is pre-selected by product. BUT: after brand is selected, the product-details do NOT change!</p>
    Selected <strong>detail</strong>:
      <pre ng-model="selected">{{detail | json}}</pre>
   </body>
</html>

See also

For using ng-options, see also plunkr example.

hc_dev
  • 8,389
  • 1
  • 26
  • 38
  • The select in my question is disabled because it's auto-selected whenever that user selects a product, that's where ProductId comes from. – Len Feb 11 '19 at 00:35
0

you need to do ng-change event in your select and call function in it that change the value of label text to the select value name. something like below In Html

ng-change="changedValue(detail.BrandId)"

In JS

$scope.changedValue = function(item) {
    //change label name here
  } 
Usama Kiyani
  • 195
  • 10
  • Thanks for posting a suggested solution but as I indicated in my question I'm looking for a solution that doesn't use javascript. – Len Jan 31 '19 at 00:49
  • you can change the label text you just need to bind the label with scope make your label like `````` and add this to change value function ```$scope.myFieldLabel = item;``` – Usama Kiyani Jan 31 '19 at 06:42
  • Thanks but I'm looking for solution without the change function in JS. – Len Jan 31 '19 at 07:55
0

fill ng-model by "option" not "option.BrandId"

then you can set title like this :

mainCtrl.products['ng-model-name'].Brand.Name

0

Here's how you could achive this:

(function () {
 "use strict";
 const app = angular.module("app", []);
  
 app.controller("app.AppCtrl", $scope => {
    $scope.selectedOption = null;
    $scope.optionList = [{_id: 1, label: 'Option 1'}, {_id: 2, label: 'Option 2'}];
  });
  
})();
body {
  margin: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="app" ng-controller="app.AppCtrl">
 <select title="{{selectedOption.label}}" class="form-control" ng-model="selectedOption">
  <option ng-repeat="option in optionList" ng-value="option"> {{option.label}}</option>
 </select>
</div>
Cristiano Soares
  • 619
  • 1
  • 9
  • 20
  • Thanks for the suggestion but I don't want to change the ng-model to 'detail.Brand' – Len Feb 07 '19 at 06:00
0

Try using ng-init,

add ng-init to your select tag and put your object index value you want to be selected by default.

e.g. Your code

<select ng-model="detail.BrandId" title="" class="form-control" disabled>
    <option ng-repeat="option in mainCtrl.products" ng-selected="option.Id === detail.ProductId" ng-value="option.BrandId">{{option.Brand.Name}}</option>
</select>

adding following code (Suppose I want index 0 by index):

ng-init="detail.BrandId = option[0].Brand.Name"

It will look like this :

<select ng-model="detail.BrandId"  ng-init="detail.BrandId = option[0].Brand.Name" title="" class="form-control" disabled>
        <option ng-repeat="option in mainCtrl.products" ng-selected="option.Id === detail.ProductId" ng-value="option.BrandId">{{option.Brand.Name}}</option>
</select>

or Check these thread's

how to use ng-option to set default value of select element

How to set default value in ng-options

Monkey D. Luffy
  • 181
  • 1
  • 3
  • 16