2

I have a select

data-ng-model="layout" ng-options="layout.url as layout.name for layout in layouts"

populated from an external json file:

{
"metaDescription": "My website description",
"metaKeywords": "keyword1, keyword2",
"siteTitle": "My Company",
"pageTitle": "Welcome ",
"layout": [
    { "name": "Cerulean",   "url": "cerulean" },
    { "name": "Cosmo",      "url": "cosmo" },
    { "name": "Cyborg",     "url": "cyborg" }
],
"test": "Lorem ipsum dolor"
}

And a controller

function httpController($scope, $http) {

    $http.get('content.json').success (function(data){

        $scope.layouts = data.layout;
        $scope.layout = $scope.layouts[2];
    });
};

The $scope.layout = $scope.layouts[2]; should set as the default value but it does not work.

It seems to be working if the JSON array is in the controller but I need to use it from an external JSON and in this case it does not work!

Any help would be appreciated.

Dayan
  • 7,634
  • 11
  • 49
  • 76
Greg
  • 473
  • 1
  • 5
  • 19

2 Answers2

1

You just need to add .url to your $scope.layout = $scope.layouts[2];

In your $http.get() Do the following.

$http.get('URLToGET')
.success(function(data){
    $scope.layouts = data.layout;
    $scope.layout = $scope.layouts[2].url;  //<--- .url
});

Your HTML will look like this:

<select data-ng-model="layout" ng-options="layout.url as layout.name for layout in layouts">
     <option value="">Select Url</option>
</select>

Here is a new updated working example

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

myApp.controller('MyCtrl', function($scope) {    
    
    $scope.data =  {
                        "metaDescription": "My website description",
                        "metaKeywords": "keyword1, keyword2",
                        "siteTitle": "My Company",
                        "pageTitle": "Welcome ",
                        "layout": [
                            { "name": "Cerulean",   "url": "cerulean" },
                            { "name": "Cosmo",      "url": "cosmo" },
                            { "name": "Cyborg",     "url": "cyborg" }
                        ],
                        "test": "Lorem ipsum dolor"
                      };
    
        $scope.layouts = $scope.data.layout;
        $scope.layout = $scope.layouts[2].url;
        
      
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
  <div ng-controller="MyCtrl">
  
    
     <select ng-model="layout" ng-options="layout.url as layout.name for layout in layouts">
          <option value="">Select Url</option>
     </select>
      <label ng-bind="layout"></label>

  </div>
  </div>

For Some clarification

When you use ng-options, the values of option tags written out by ng-options will always be the index of the array item the option tag relates to. This is because Angular actually allows you to select entire objects with select controls, and not just primitive types.

Refer to a great answer by Ben Lesh for details on ngOptions as well as the ngOptions official docs.

Community
  • 1
  • 1
Dayan
  • 7,634
  • 11
  • 49
  • 76
  • I agree, but try to make this from an external JSON file! BTW my JSON as other values, this is the reason why i have the layout : [ – Greg Mar 10 '15 at 15:13
  • I have updated the JSON as it is really (please see original question). It already as the opening/close {}. What I need to get it the url to inject in href="themes/{{layout}}/stylesheet.css" The Json is hosted here http://www.mailforce.fr/lists/content.json – Greg Mar 10 '15 at 15:44
  • @Artefact I see what you were referring to, check my update. Read the whole thing i pretty much re-wrote it :) it works now – Dayan Mar 10 '15 at 16:01
  • I get $scope.layouts.layout is undefined – Greg Mar 10 '15 at 16:08
  • Thats because on my example i was retrieving a JSON object from your whole JSON. Check my updated answer which shows you the `$http.get`. Test it out with `JSON.parse(data.data)` if that doesnt do it then change the `data.data` to just `data` and let me know so i can update answer please. – Dayan Mar 10 '15 at 16:16
  • I get SyntaxError: JSON.parse: $scope.layouts = JSON.parse(data).layout; – Greg Mar 10 '15 at 16:26
  • Ok i went ahead and tested this using a REST Mockup service `https://www.mockable.io`, awesome site. Using their trial i was able to replicate your `environment` and the incoming JSON you provided. So, with that said Look at my updated answer. Your `ng-options` was indeed correct from the beginning. Just change your `.success()` as I have it in the answer. All you were missing was - `.url` ;) – Dayan Mar 10 '15 at 17:08
  • Thanks you Dayan, but on my hand $scope.layouts = data.layout; $scope.layout = $scope.layouts[2].url; does not put url2 as defautlt in the selest :( – Greg Mar 10 '15 at 18:02
  • Ok, do you want to display The `name` values in the dropdown and when one is selected then the model will equal the `url`? Or vice versa? – Dayan Mar 10 '15 at 18:11
  • Yes, I want to display the name value in the dropdown with a default on select and when one is selected get the corresponding URL which is in fact a folder name to add to href="themes/{{layout}}/stylesheet.css" – Greg Mar 11 '15 at 07:52
  • Then what i provided is correct. If that is the JSON you are refering to then I tested it externally via a 3rd party REST mockup service and locally. Works just fine, seems likr your doing something extra thats conflicting... – Dayan Mar 11 '15 at 12:37
  • That was not working. I have a split $http.get > success in 2 parts. 1 with $scope.layouts = data.layout and one with $scope.layout = $scope.layouts[2].url; and it works now. – Greg Mar 11 '15 at 15:51
0

Modify your ng-options like this:

ng-options="layout as layout.name for layout in layouts"

Your ng-options expression is in the following format:

select as label for value in array

Per angular documentation the definition of select is:

The result of this expression will be bound to the model of the parent element. If not specified, select expression will default to value.

You are binding the url property to the model not the whole object. That is the problem.

nweg
  • 2,825
  • 3
  • 22
  • 30
  • Add $scope.layout = {} at the top of your controller. – nweg Mar 10 '15 at 14:55
  • Sorry but it does not work. I mean, my code works as I get the right folder to populate - but I am not able to get a default value to the select – Greg Mar 10 '15 at 15:01
  • I think you need to update the following line $scope.layouts = data.layout; to just $scope.layouts = data; – nweg Mar 10 '15 at 15:03
  • without success :( It works fine from an array in the Controller but not from an external .json file – Greg Mar 10 '15 at 15:32