ng-change event not firing inside the loop
Asked Answered
M

2

5

function friendControllerTest($scope, $http) {
    $scope.loading = true;
    $scope.addMode = false;
    $scope.countryList = [];
    $scope.stateList = [];

    function getAllCountry() {
        $http({
            method: 'Get',
            url: '/Home/GetCountry'
        }).success(function (data) {
            $scope.countryList = data;
        }).error(function () {
            $scope.errorMessage = 'Not found';
        });
    }

    function getStatebyCountryId(Id) {
        $scope.stateList = null;
        if (Id) {           // Check here country Id is null or not
            $http({
                method: 'POST',
                url: '/Home/GetStateByCountryId/',
                data: JSON.stringify({ CountryId:Id })
            }).success(function (data) {
                $scope.stateList = data;
            }).error(function (data) {
                alert(data.message);
                $scope.message = 'not found';
            });
        }
        else {
            $scope.stateList = null;
        }
    }


    $scope.GetStatesList = function (id) {
        if (id) {           // Check here country Id is null or not
            $http({
                method: 'POST',
                url: '/Home/GetStateByCountryId/',
                data: JSON.stringify({ CountryId: id })
            }).success(function (data) {
                $scope.stateList = data;
            }).error(function (data) {
                alert(data.message);
                $scope.message = 'not found';
            });
        }
        else {
            $scope.stateList = null;
        }
    }



    $scope.myMethod = function () {
        var text = $scope.newfriend.SearchText;
        $http.get('../Home/GetFriendsList', { params: { 'text': text } }).success(function (data) {
            $scope.friends = data;
        })
          .error(function () {
              $scope.error = "An Error has occured while loading posts!";
          });
    }


    $http.get('../Home/GetFriendsList').success(function (data) {
        alert("list called")
        $scope.friends = data;
        $scope.loading = false;
    })
   .error(function () {
       $scope.error = "An Error has occured while loading posts!";
       $scope.loading = false;
   });

    $scope.toggleAdd = function () {
        $scope.addMode = !$scope.addMode;
        if ($scope.addMode) {
            getAllCountry();
        }
    };

    $scope.toggleEdit = function () { 
        this.friend.editMode = !this.friend.editMode;
        getAllCountry();
        if (this.friend.Country.Id > 0)
            getStatebyCountryId(this.friend.Country.Id);
    };

    $scope.add = function () {
        $scope.loading = true;
        var newfriend = {
            firstname: $scope.newfriend.firstname,
            lastname: $scope.newfriend.lastName,
            address: $scope.newfriend.address,
            postalcode: $scope.newfriend.PostalCode,
            notes: $scope.newfriend.Notes,
            CountryId: $scope.newfriend.Country.Id,
            StateId: $scope.newfriend.State.Id
        }
        $http.post('../Home/AddFriends', newfriend).success(function (data) {
            alert("Added Successfully!!");
            $scope.addMode = false;
            $scope.friends.push(data);
            $scope.loading = false;
            $scope.newfriend = "";
        }).error(function (data) {
            $scope.error = "An Error has occured while Adding Friend! " + data;
            $scope.loading = false;
        });
    };

    $scope.save = function () {
        $scope.loading = true;
        var frien = this.friend;
        $http.put('../Home/EditFriend', frien).success(function (data) {
            alert("Saved Successfully!!");
            frien.editMode = false;
            $scope.loading = false;
        }).error(function (data) {
            $scope.error = "An Error has occured while Saving Friend! " + data;
            $scope.loading = false;
        });
    };

    $scope.deletefriend = function () {
        $scope.loading = true;
        var friendid = this.friend.Id;
        $http.delete('../Home/RemoveFriend/' + friendid).success(function (data) {
            alert("Deleted Successfully!!");
            $.each($scope.friends, function (i) {
                if ($scope.friends[i].Id === friendid) {
                    $scope.friends.splice(i, 1);
                    return false;
                }
            });
            $scope.loading = false;
        }).error(function (data) {
            $scope.error = "An Error has occured while Saving Friend! " + data;
            $scope.loading = false;
        });
    };
}
<html data-ng-app="" data-ng-controller="friendControllerTest">
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
  </head>
  
  <body>
    <div class="container">
        <strong class="error">{{ error }}</strong>
        <div id="mydiv" data-ng-show="loading">
            <img src="Images/ajax-loader1.gif" class="ajax-loader" />
        </div>
       
        <p data-ng-hide="addMode">
            <a data-ng-click="toggleAdd()" href="javascript:;" class="btn btn-primary">Add New
            </a>
        </p>
        <form name="addFriend" data-ng-show="addMode" style="width: 600px; margin: 0px auto;">
            <label>FirstName:</label><input type="text" data-ng-model="newfriend.firstname" required />
            <label>LastName:</label><input type="text" data-ng-model="newfriend.lastName" required />
            <label>Address:</label><input type="text" data-ng-model="newfriend.address" required />
            <label>Country:</label>
           
            <select ng-model="newfriend.Country" ng-options="c.Name for c in countryList track by c.Id" ng-change="GetStatesList(newfriend.Country.Id)">
                <option value="">Select Country</option>
            </select>
            <label>State:</label>

            <select ng-model="newfriend.State" ng-options="s.Name for s in stateList track by s.Id">
                <option value="">Select State</option>
            </select>
            <label>PostalCode:</label><input type="text" data-ng-model="newfriend.PostalCode" required />
            <label>Notes:</label><input type="text" data-ng-model="newfriend.Notes" required />
            <br />
            <br />
            <input type="submit" value="Add" data-ng-click="add()" data-ng-disabled="!addFriend.$valid" class="btn btn-primary" />
            <input type="button" value="Cancel" data-ng-click="toggleAdd()" class="btn btn-primary" />
            <br />
            <br />
        </form>
        <table class="table table-bordered table-hover" style="width: 800px">
            <tr>
                <th>#</th>
                <td>FirstName</td>
                <th>LastName</th>
                <th>Address</th>
                <th>Country</th>
                <th>State</th>
                <th>PostalCode</th>
                <th>Notes</th>
            </tr>

            <tr data-ng-repeat="friend in friends">
                <td><strong>{{ friend.Id }}</strong></td>
                <td>
                    <p data-ng-hide="friend.editMode">{{ friend.firstname}}</p>
                    <input data-ng-show="friend.editMode" type="text" data-ng-model="friend.firstname" />
                </td>
                <td>
                    <p data-ng-hide="friend.editMode">{{ friend.lastname }}</p>
                    <input data-ng-show="friend.editMode" type="text" data-ng-model="friend.lastname" />
                </td>
                <td>
                    <p data-ng-hide="friend.editMode">{{ friend.address }}</p>
                    <input data-ng-show="friend.editMode" type="text" data-ng-model="friend.address" />
                </td>
                <td>
                    <p data-ng-hide="friend.editMode">{{ friend.Country.Name }}</p>
                    <select data-ng-show="friend.editMode" ng-model="friend.Country" ng-options="c.Name for c in countryList track by c.Id" ng-change="$parent.GetStatesList(friend.Country.Id)">
                        <option value="">Select Country</option>
                    </select>
                </td>
                <td>
                    <p data-ng-hide="friend.editMode">{{friend.State.Name }}</p>
                    <select data-ng-show="friend.editMode" ng-model="friend.State" ng-options="s.Name for s in stateList track by s.Id">
                        <option value="">Select State</option>
                    </select>
                </td>


                <td>
                    <p data-ng-hide="friend.editMode">{{ friend.postalcode }}</p>
                    <input data-ng-show="friend.editMode" type="text" data-ng-model="friend.postalcode" />
                </td>

                <td>
                    <p data-ng-hide="friend.editMode">{{ friend.notes }}</p>
                    <input data-ng-show="friend.editMode" type="text" data-ng-model="friend.notes" />
                </td>
                <td>
                    <p data-ng-hide="friend.editMode"><a data-ng-click="toggleEdit(friend)" href="javascript:;">Edit</a> | <a data-ng-click="deletefriend(friend)" href="javascript:;">Delete</a></p>
                    <p data-ng-show="friend.editMode"><a data-ng-click="save(friend)" href="javascript:;">Save</a> | <a data-ng-click="toggleEdit(friend)" href="javascript:;">Cancel</a></p>
                </td>
            </tr>
        </table>
        <hr />
    </div>
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @Scripts.Render("~/bundles/angularjs")
    <script src="~/Scripts/MyScript.js"></script>
</body>

I am trying to open my Country and state dropdown in edit mode and so far i am successfull in that.

But the only problem is when i am clicking on any record to open in edit mode my both country and state dropdown are binding correctly but when i am selecting other country from country dropdown then my ng-change is not firing and i dont know why.

This is my view for adding a new record:

<select ng-model="newfriend.Country" ng-options="c.Name for c in countryList track by c.Id" ng-change="GetStatesList()">
                <option value="">Select Country</option>
            </select>

            <label>State:</label>
            <select ng-model="newfriend.State" ng-options="s.Name for s in stateList track by s.Id">
                <option value="">Select State</option>
            </select>

My Controller:

    function friendControllerTest($scope, $http) {
             $scope.GetStatesList = function () {
                  //server side call to fetch state by country id
            }
 $scope.toggleEdit = function () { 
            this.friend.editMode = !this.friend.editMode;
            getAllCountry();
            if (this.friend.Country.Id > 0)
                getStatebyCountryId(this.friend.Country.Id);
        };


      };

My Display records view:

<table class="table table-bordered table-hover" style="width: 800px">
 <tr data-ng-repeat="friend in friends">
  <td>
                    <p data-ng-hide="friend.editMode">{{ friend.Country.Name }}</p>
                    <select data-ng-show="friend.editMode" ng-model="friend.Country" ng-options="c.Name for c in countryList track by c.Id" ng-change="GetStatesList()">
                        <option value="">Select Country</option>
                    </select>
                </td>
                <td>
                    <p data-ng-hide="friend.editMode">{{friend.State.Name }}</p>
                    <select data-ng-show="friend.editMode" ng-model="friend.State" ng-options="s.Name for s in stateList track by s.Id">
                        <option value="">Select State</option>
                    </select>
                </td>

</tr>
<table>



public class HomeController : Controller
    {
        //
        // GET: /Home/
        private FriendsEntities db = new FriendsEntities();
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult GetFriendsList(string text)
        {

            var data = db.Friends.Select
                                (
                                    d => new FriendModel
                                    {
                                        Id=d.Id,
                                        firstname = d.firstname,
                                        lastname = d.lastname,
                                        address = d.address,
                                        notes = d.notes,
                                        postalcode = d.postalcode,
                                        Country = d.Country.Friends.Select
                                                                   (
                                                                        x => new CountryModel
                                                                        {
                                                                            Id=x.Country.Id,
                                                                            Name = x.Country.Name
                                                                        }
                                                                   ).FirstOrDefault(),
                                        State = d.State.Friends.Select
                                                               (
                                                                    s => new StateModel
                                                                    {
                                                                        Id=s.State.Id,
                                                                        Name = s.State.Name
                                                                    }
                                                               ).FirstOrDefault()

                                    }
                                ).ToList();
           return Json(data, JsonRequestBehavior.AllowGet);
        }

        [HttpPost]
        public ActionResult AddFriends(Friends FriendsModel)
        {
            var result = db.Friends.Add(FriendsModel);
            db.SaveChanges();
            var data = db.Friends.Where(t => t.Id == result.Id).Select
                                     (
                                            d => new FriendModel
                                            {
                                                Id=d.Id,
                                                firstname = d.firstname,
                                                lastname = d.lastname,
                                                address = d.address,
                                                notes = d.notes,
                                                postalcode = d.postalcode,
                                                Country = d.Country.Friends.Select
                                                                   (
                                                                        x => new CountryModel
                                                                        {
                                                                            Id=x.Country.Id,
                                                                            Name = x.Country.Name
                                                                        }

                                                                   ).FirstOrDefault(),
                                                State = d.State.Friends.Select
                                                                       (
                                                                           b => new StateModel
                                                                           {
                                                                               Id=b.State.Id,
                                                                               Name = b.State.Name
                                                                           }
                                                                       ).FirstOrDefault()
                                            }

                                     ).SingleOrDefault();

            return Json(data);
        }


        public ActionResult RemoveFriend(int id)
        {
            Friends friend = db.Friends.Find(id);
              db.Friends.Remove(friend);
              db.SaveChanges();
              return Json(friend);
        }

        public JsonResult GetCountryState()
        {
            List<CountryModel> Country = new List<CountryModel>().ToList();
            Country.Add(new CountryModel() { Id = 0, Name = "Select Country" });
            var Data = db.Country.Select
                                (
                                    d => new CountryModel
                                    {
                                        Id = d.Id,
                                        Name = d.Name,
                                        State = d.State.Select
                                        (
                                             x => new StateModel
                                             {
                                                 Id = x.Id,
                                                 Name = x.Name
                                             }
                                        ).ToList()
                                    }
                                ).ToList();
            Country.AddRange(Data);
            return Json(Country, JsonRequestBehavior.AllowGet);
        }

        public JsonResult GetCountry()
        {
            var Data = db.Country.Select
                                (
                                    d => new CountryModel
                                    {
                                        Id = d.Id,
                                        Name = d.Name,
                                    }
                                ).ToList();
            return Json(Data, JsonRequestBehavior.AllowGet);
        }

        public JsonResult GetStateByCountryId(int CountryId)
        {
                var getStateList = db.State.Where(p => p.CountryId == CountryId).Select(x => new { x.Id, x.Name }).ToList();
                return Json(getStateList, JsonRequestBehavior.AllowGet);
        }




        [HttpPut]
        public ActionResult EditFriend(Friends  FriendModel)
        {
            Friends friend = db.Friends.Find(FriendModel.Id);
            friend.firstname = FriendModel.firstname;
            friend.lastname = FriendModel.lastname;
            friend.postalcode = FriendModel.postalcode;
            friend.notes = FriendModel.notes;
            friend.address = FriendModel.address;
            friend.CountryId = FriendModel.Country.Id;
            friend.StateId = FriendModel.State.Id;
            db.SaveChanges();

            var friendModel = new FriendModel();
            friendModel.Id = friend.Id;
            friendModel.firstname = friend.firstname;
            friendModel.lastname = friend.lastname;
            friendModel.postalcode = friend.postalcode;
            friendModel.notes = friend.notes;
            friendModel.address = friend.address;
            friendModel.CountryId = friend.CountryId;
            friendModel.StateId = friend.StateId;
            return Json(friendModel);
        }
    }



public class BundleConfig
    {
        public static void RegisterBundles(BundleCollection bundles)
        {
            bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                        "~/Scripts/jquery-{version}.js"));

            bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                        "~/Scripts/jquery.validate*"));

            // Use the development version of Modernizr to develop with and learn from. Then, when you're
            // ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
            bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                        "~/Scripts/modernizr-*"));

            bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
                      "~/Scripts/bootstrap.js",
                      "~/Scripts/respond.js"));

            bundles.Add(new StyleBundle("~/Content/css").Include(
                      "~/Content/bootstrap.css",
                      "~/Content/site.css"));


            bundles.Add(new ScriptBundle("~/bundles/angularjs").Include(
                      "~/Scripts/angular.min.js"));

            bundles.Add(new ScriptBundle("~/bundles/appjs").Include(
                     "~/Scripts/app/customerCtrl.js"));
        }
    }
Macronucleus answered 20/3, 2015 at 7:19 Comment(27)
can you please add jsfiddle?Orts
ok i will add but any partial solution you want to give?Macronucleus
You using two selection list if user select first list (country) item depending on that (states) second list data will load byng-change="GetStatesList()" . your were using another view to display this data with user EDIT option . if user change country again you call "GetStatesList() " .but here ng-change not working this may be scope issue between controllers or ng-model not properly usedOrts
yaa thats the problem.Macronucleus
Post your solution as answer . it will help othersOrts
yaa but i dont have any solution that is why i have asked here.Macronucleus
i posted my answer.it may help you ,otherwise add jsfiddleOrts
First solution will help you shortly. don't forget add DI as $rootScopeOrts
country and state list does not change . so you can use as factory and add as DI in your controller to use .Orts
Let us continue this discussion in chat.Macronucleus
try $parent.GetStatesList() inside ng-repeat ng-change eventDipstick
@pankajparkar:yaa it is calling that method and by injecting $rootScope in controller and doing this: function friendControllerTest($scope, $http,$rootScope) { $rootScope.GetStatesList = function () {Macronucleus
@pankajparkar:with above code too(as suggested by srini vasan) this method is callingMacronucleus
adding method to the $rootScope doesn't sounds like good solution..Dipstick
i think $parent scope does not work in this situationOrts
@J.SRINIVasan why it doesn't work? it would workDipstick
i suggest simple solution . other wise use factory / service methods . this only good practice than $parent ( $parent will work only when using directives )Orts
@J.SRINIVasan:yaa $parent workedMacronucleus
@pankajparkar:why using $rootscopet isnt a good solution?Macronucleus
sorry @pankajparkar . post as answer . you are correct. but i think nothing wrong with $rootScoop. may i know why using $rootscopet isnt a good solution?Orts
@J.SRINIVasan read here michaeleconroy.blogspot.in/2013/09/… , I'm saying why to make available method to all childs for fixing it in one placeDipstick
@pankajparkar:can you please explain me a little bit that how it worked with $parent??Macronucleus
@pankajparkar thats why i suggest 2. write service method/factory . but easy solution is rootscope. i want why $parent , why not $rootScope . but no answer in that blogOrts
$parent only work , if display controller is child scope of friendControllerTest . but rootscope work overall appOrts
@J.SRINIVasan you are not getting my point, there is no need to pollute $rootScope to get access it inside ng-repeatDipstick
@Maria Pithia please use $parent, because Mr.pankajparkar have experience .Net MVC . it would be good solution than me .Orts
@J.SRINIVasan hey experience doesn't matter, the solution does matter while fixing problem..Thanks :) I've updated the answerDipstick
D
6

Your problem is you are accessing scope inside ng-repeat & Directive like ng-repeat, ng-switch, ng-view, ng-include& ng-if does create a new scope from currently running scope. For referring parent scope method or variable you need use $parent, that provides access to parent

You should first need to read Understanding of Angular Scope Inheritance.

Plunkr for Explanation of the same.

Below is the only change required inside you markup

ng-change="GetStatesList()" 

to

ng-change="$parent.GetStatesList()"

Hope this could help you, Thanks.

Dipstick answered 20/3, 2015 at 10:25 Comment(0)
O
2

ng-change event not firing in Angularjs

You have two views .

 1. Add record( give info to country ,state)
 2. Display stored records (with edit mode to change country,state)

In your add record view ng-change="GetStatesList()" fires and show state list by calling GetStatesList() function friendControllerTest when country selected (model value changed) .

Your **Display records view has its own controller.it doesn't have GetStatesList() function ,so that ng-change not working .

Two solution for this issue is:

 1. Make "$scope.GetStatesList()" to "$rootScope.GetStatesList()"- rootscope
 2. Write service/factory method then you can use wherever you want.

EDIT: but using $parent.GetStateList() is good practice as @pankajparkar's soltution

Orts answered 20/3, 2015 at 8:49 Comment(4)
but cant this be done without using method or factory??Macronucleus
modify you method to $rootScope and add $rootScope DIOrts
that is two solution . first one easy to useOrts
your service/factory suggestion +1 forDipstick

© 2022 - 2024 — McMap. All rights reserved.