A Small Form and Cascading Drop Down with AngularJS

by mickeyvip

HTML

<div ng-app="App">
    <fieldset ng-controller="NewPropertyController">
        <div class="field">
            <label for="resident-name">Resident Name</label>
            <input type="text" id="resident-name" ng-model="prop.residentName" />
        </div>
        <div class="field">
            <label for="street-name">Street</label>
            <input type="text" id="street-name" ng-model="prop.streetName" />
        </div>
        <div class="field">
            <label for="number-name">Number</label>
            <input type="text" id="number-name" ng-model="prop.numberName" />
        </div>
        <div class="field">
            <label for="country-name">CountryName</label>
            <select id="country-name" name="country-name" ng-model="prop.country" ng-options="country.name for (id, country) in countries" ng-change="resetCity()">
                <option value="">Choose Country...</option>
            </select>
        </div>
        <div class="field">
            <label for="city-name">City Name</label>
            <select id="city-name" name="city-name" ng-model="prop.city" ng-options="city.name for city in getCities()">
                <option value="">Choose City...</option>                
            </select>
        </div>
        <button id="submit-command" ng-disabled="!prop.isValid()" ng-click="submitClick()">Submit</button>
        <div class="field">
            Debug View:
            <pre>prop = {{prop | json}}</pre>            
        </div>
    </fieldset>
</div>

SCSS

body {
    font-family: Arial, Verdana;
}
fieldset {
    width: 500px;
    padding: 20px;
    background: #f0f0f0;
    overflow:auto;
    
    /* Border style */
    border: 1px solid #cccccc;
    border-radius: 7px;
    box-shadow: 2px 2px 2px #cccccc;
    
    .field {
        float: left;
        clear: both;
    }
    
    label {
        text-shadow: 2px 2px 2px #ccc;
        display: block;
        float: left;       
        width: 120px;
        line-height: 25px;
        font-size: 15px;
    }
    input, select {
        font-size: 15px;
        padding: 5px;
        border: 1px solid #b9bdc1;
        color: #797979;
        float: left;
        margin-bottom: 5px;
        width: 130px;    
    }
    select {
        width: (130 + 10)px;
    }
    button {
        float: right;
        clear: both;        
        margin:10px 55px 10px 0;
        font-weight: bold;
        line-height: 1;
        padding: 6px 10px;
        cursor:pointer;
        color: #fff;
     
        text-align: center;
        text-shadow: 0 -1px 1px #64799e;
     
        /* Background gradient */
        background: #a5b8da;
        background: -moz-linear-gradient(top, #a5b8da 0%, #7089b3 100%);
        background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#a5b8da), to(#7089b3));
     
        /* Border style */
        border: 1px solid #5c6f91;
        border-radius: 10px;
     
        /* Box shadow */
        box-shadow: inset 0 1px 0 0 #aec3e5;        
    
        &[disabled] {
            opacity: 0.5;            
        }
    }
}

JavaScript

var app = angular.module("App", []);
app.controller("NewPropertyController", ['$scope', function($scope) {
    var prop = $scope.prop = {
        residentName: "John Doe",
        streetName: "Sesame",
        numberName: "5",
        country: null,
        city: null,
        
        isValid: function() {
            var isValid = (this.residentName || false) && 
                (this.streetName || false) && 
                (this.numberName || false) && 
                (this.city || false) && 
                (this.country || false);

            return isValid;
        }
    };
    
    $scope.resetCity= function() {
        $scope.prop.city = null;
    };
    
    $scope.getCities = function() {
        var currentCities = [];
        if ($scope.prop.country) {
            for(var i = 0, count = $scope.citiesByCountry.length; i < count; i++) {
                var curr = $scope.citiesByCountry[i];
                if (curr.countryId === $scope.prop.country.id) {
                    currentCities = curr.cities;
                    break;
                }
            }
        }
        return currentCities;
    };

    var submitClick = $scope.submitClick = function() {
        alert("Submitting data...");
    };
    
    // load countries
    var countries = $scope.countries = [
        {
            id: 1,
            name: "Israel"},
        {
            id: 2,
            name: "USA"},
        {
            id: 3,
            name: "Canada"
        }
    ];
    
    // load cities
    var citiesByCountry = $scope.citiesByCountry = [
    {
        countryId: 1,
        cities: [
            {
                id: 11,
                name: "Tel Aviv"},
            {
                id: 12,
                name: "Jerusalem"},
            {
                id: 13,
                name: "Haifa"},
            {
                id: 14,
                name: "Eilat"}
            ]
    },
    {
        countryId: 2,
        cities: [
            {
               ...