Link to home
Start Free TrialLog in
Avatar of Camillia
CamilliaFlag for United States of America

asked on

Angular - following an example by an expert here (Julian)

Julian Hanson helped me with this and came up with an example here

Julian's example

I want to use this for Country and State dropdowns. I'm getting an error and I don't know what I'm missing.
So, when user selects US, I want to have US states displayed.If canada, display Canada states.

It would be better if the States ddl is not even populated until a country is selected...just like the example in the link above....teh second ddl is not populated until something from first one is selected.

1. State dataset looks like this. States dataset has data for both US and Canada states. It has a CountryId column to indicate if it's US or Canada

Array[64]
 0: Object
    CountryId: 1
     Id: 1
     StateCode: "AL"
     StateName : "Alabama"
  1: Object
    CountryId: 1
     Id: 2
     StateCode: "AK"
     StateName : "Alaska"
  62: Object
     CountryId: 2
     Id: 62
     StateCode: "QC"
     StateName : "Quebec"

2. Dataset for Country looks like this
Array[2]
 0: Object
     $$hashKey: "object:620"
     Id: 1
     Name: US
 1: Object
     $$hashKey: "object:621"
     Id: 1
     Name: Canada

3. Country code looks like this

  <select id="country" name="country" ng-required=selectedContactType.Id ==1"
                 ng-options="opt.Name for opt in allCountries" ng-model="selectedCountry">
               <option value=""> select country </option>
          </select>

Open in new window


4. State looks like this. This works and I see both US and Canada states in the ddl

  <select id="states" name="states" ng-required=selectedContactType.Id ==1"
                 ng-options="opt.StateCode for opt in allStates track by opt.Id" ng-model="selectedState">
               <option value=""> select country </option>
          </select>

Open in new window


5. I changed the state code to this but getting an error -> [filter:notarray] expected array but received 1.

Note: page loads and Country ddl already has US in it because user's dataset has this value (user had already selected US, saved and now I'm pulling up the page). State ddl has nothing and I see that error.

I know what the error means. That filter should return an array but it's not and I don't know why. I'll keep playing around with it.

 ng-options="opt.StateCode for opt in allStates track by opt.Id | filter: {CountryId: country.Id}:true"

Open in new window


6. If I remove
track by opt.Id

Open in new window

, page loads and no error but then the filtering isn't working.

7. Made this change as well. No error but filter doesn't work...by that I mean...I choose US and I still see all the states...both for canada and US

  ng-options="opt.Name for opt in allCountries track by opt.Id"

And 

ng-options="opt.StateCode for opt in allStates  | filter: {CountryId: country.Id}:true"

Open in new window

Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

You need to fix your filter parameters by passing in an object that is used to match the states array.

Tell me if this works for you and if so we can discuss
HTML
	<select id="country" name="country" ng-required=selectedContactType.Id ==1"
		ng-options="opt.Name for opt in allCountries" ng-model="selectedCountry">
		<option value=""> select country </option>
	</select>
	<select id="states" name="states" ng-required=selectedContactType.Id ==1" ng-disabled="!selectedCountry"
		ng-options="opt.StateCode for opt in allStates | filter:{CountryId: selectedCountry.Id}" ng-model="selectedState">
		<option value=""> select country </option>
	</select>

Open in new window

JavaScript
(function() {
  'use strict';
  angular.module('app',['smart-table'])
    .controller('mainCtrl', mainController);

  function mainController($scope)
  {
	$scope.allCountries =[{
		Id: 1,
		Name: "US"
	},{
		Id: 2,
		Name: "Canada"
	}];
	
    $scope.allStates = [{
		CountryId: 1,
		Id: 1,
		StateCode: "AL",
		StateName : "Alabama"
	},{
		CountryId: 1,
		Id: 2,
		StateCode: "AK",
		StateName : "Alaska"
	},{
		CountryId: 2,
		Id: 62,
		StateCode: "QC",
		StateName : "Quebec"
	}];
  }
})();

Open in new window

Working sample here

EDIT: Updated to add ng-disabled on States <select>
Avatar of Camillia

ASKER

let me see. I'll post back soon.
This works but now I have a problem.

1. I had the States like this (I had track by opt.Id). With this, I could get the Id of the state

<option label="AL" value="1"[/b]> AL </option>

 ng-options="opt.StateCode for opt in allStates track by opt.Id"

Open in new window


2. Changing it to this and removing the track b opt.Id, I don't get the value...I see something like this (you can see it in your example too)

<option label="AL" value="object:618"> AL </option>

ng-options="opt.StateCode for opt in allStates | filter:{CountryId: selectedCountry.Id}"

Open in new window


3. If I change it to this, then I don't get any states in the ddl

ng-options="opt.StateCode for opt in allStates track by opt.Id | filter:{CountryId: selectedCountry.Id}"

Open in new window


so, how I can keep your fix but still get the value of the state (stateId)?
That just means that the option is linked to an object.

The question is how you want to use the values - it should not matter what is in the option value=""

I have updated the sample to included the following
	<div>
		Selected Country: {{selectedCountry.Name}}<br/>
		Selected State: {{selectedState.StateName}}<br/>
		Selected State (object) : {{selectedState}}
	</div>

Open in new window

You can see it here
Let me see. The reason I want the "value" is because I need to save the State Id back in the database. I can't save "object:618". But let me look at your change
Yes,  I understand it now. Let me test one more thing. I think I have one more question.
ASKER CERTIFIED SOLUTION
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Ah, I think your latest one is what I need because user might have selections already that I read back and pre-populate.
Let me see.
I wonder why mine isn't working. I bring up the page and load the data. I see Country ddl has value of "US". I see state has value of "GA".
Now, I expand the States ddl and I see ALL the states...even the Canada ones.

I have to type in the code by hand, I'll post back soon
Ah, I had a typo. It works. Thank you so much.
I understand it as well.
You are most welcome.