简体   繁体   中英

Angular changing object in scope doesn't change view

Screencast: http://screencast-o-matic.com/watch/cDjX00isoo
All Javascript: http://fontget.com/js/all.js (at the bottom)
Demo of the issue: http://www.fontget.com

So I have this issue that I have been dealing with for a bit and can't seem to be able to figure it out. I am trying to give users the option of sorting the results from the database by clicking on a radio button with the specific filter.

When I click on the radio button I can see in the console that the correct url is grabbed using AJAX but the list is not getting updated in the view.

The page works when it is loaded for the first time (no sort filters).

The controller:

FontGet.controller('mainController', ['$scope', 'FontService', '$location', '$rootScope', '$routeParams', function($scope, FontService, $location, $rootScope, $routeParams) {
    $rootScope.hideFatMenu = false;
    $scope.navCollapsed = true;
    $scope.isSettingsCollapsed = true;
    $rootScope.header = "Welcome to FontGet.com!";
    $scope.sortBy = 'new';

    $scope.fonts = {
        total: 0,
        per_page: 10,
        current_page: ((typeof($routeParams.page) !== 'undefined') ? $routeParams.page : 1),
        loading: true
    };

    $scope.setPage = function() {
        FontService.call('fonts', { page: $scope.fonts.current_page, sort: $scope.sortBy }).then( function(data) {
            $scope.fonts = data.data;
            $scope.fonts.loading = false;

            document.body.scrollTop = document.documentElement.scrollTop = 0;
        });
    };


    $scope.$watch("sortBy", function(value) {
        $scope.setPage();
    });

    $scope.$watch("searchQuery", function(value) {
        if (value) {
            $location.path("/search/" + value);
        }
    });


    $scope.categories = FontService.categories();
    $scope.setPage();
}]);

The View:

<div class="fontdd" ng-repeat="font in fonts.data" >
    <!-- Stuff goes here. This is populated correctly when page initially loads -->
</div>

The sort buttons:

<ul class="radiobtns">
    <li>
        <div class="radio-btn">
            <input type="radio" value="value-1" id="rc1" name="rc1" ng-model="sorts" ng-change="sortBy = 'popular'">
            <label for="rc1" >Popularity</label>
        </div>
    </li>
    <li>
        <div class="radio-btn">
            <input type="radio" value="value-2" id="rc2" name="rc1" ng-model="sorts" ng-change="sortBy = 'trending'">
            <label for="rc2">Trending</label>
        </div>
    </li>
    <li>
        <div class="radio-btn">
            <input type="radio" value="value-4" id="rc4" name="rc1" checked="checked" ng-model="sorts" ng-change="sortBy = 'new'">
            <label for="rc4">Newest</label>
        </div>
    </li>
    <li>
        <div class="radio-btn">
            <input type="radio" value="value-3" id="rc3" name="rc1" ng-model="sorts" ng-change="sortBy = 'alphabetical'">
            <label for="rc3">Alphabetical</label>
        </div>
    </li>
</ul>

You will notice that the ng-model for the radio buttons is not set to sortBy . The reason for this is that if I set it to sortBy the AJAX call is made 4 times (no clue why thi is happening).

You're using a $scope.$watch function to watch for changes in the sortBy scope variable. You should try removing the watch and change your sort buttons' ng-change event to this:

    <div class="radio-btn">
        <input type="radio" value="value-1" id="rc1" name="rc1" ng-model="sorts" ng-change="Sort('popular')">
        <label for="rc1" >Popularity</label>
    </div>

In your controller, create a Sort() function:

$scope.Sort = function(sortBy) {
   $scope.sortBy = sortBy;
   $scope.setPage();
}

You don't really need to use $watch when you can just call a function and pass in the appropriate information.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM