Controller doesn't work after URL change

旧城冷巷雨未停 提交于 2019-12-13 06:01:29

问题


In short:

I have a controller that triggers some jQuery in my AngularJS web page to fade out a play button and a corresponding image. But, when the URL changes, the controller fails to work on subsequent pages. I'm using a dynamic URL, and I think that's why my controller is breaking.

Detail

I've organized my controllers by having one for each page of my website app. Here you can see how my routes are setup:

angular.module('100_Ages', ['mydirectives', 'ngResponsiveImages']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
    when('/100_Ages', {templateUrl: 'partials/splash.html', controller: SplashCtrl}).
    when('/100_Ages/nav', {templateUrl: 'partials/nav.html', controller: NavCtrl}).
    when('/100_Ages/about', {templateUrl: 'partials/person-list.html', controller: AboutCtrl}).
    when('/100_Ages/0', {templateUrl: 'partials/splash.html', controller: SplashCtrl}).
    when('/100_Ages/:personId', {templateUrl: 'partials/person.html', controller: DetailCtrl}).
    otherwise({redirectTo: '/100_Ages'});
}]);

And here is the controller in question:

function DetailCtrl($scope, $routeParams, $http) {
// Pull down a JSON file with my data to populate Angular template
  $http.get('person.json').success(function(data) {
// matches person's id to route.
    angular.forEach(data, function(person) {
          if (person.id == $routeParams.personId) 
            $scope.person = person;
        });
    });
// start of attempt to integrate button click functionality.
  $scope.$on('$routeChangeSuccess', function(){
    $.noConflict();
      jQuery(function(){
        jQuery("#playButton").click(function(){
          jQuery("#person_photo").fadeOut('9000');
          jQuery("#playButton").fadeOut('9000');
          jQuery("#player").fadeIn('9000');
        });
      });
  });
}

I'm using jQuery here because I simply couldn't figure out how to do this in Angular. Anyways, when I refresh the page and click on the button image, it works. But, I have a 'next' link that increments the route by '1' to go to the next page in my app (a list of 100 people, with one person on each page).

When I go to a different page using this link, my jQuery no longer works. I'm guessing this is because the route isn't changing, even though the URL is. Anyway to make this work with my dynamic route? Thanks.


回答1:


A couple things...

1) You don't need $.noConflict(). Angular and jQuery play nice.

2) You should should put DOM scripting within an Angular Directive rather than a controller. Here's an example...

Directive*:

(function () {

    function personPlayerDirective() {
        return function (scope, $element, attr) {
            $element.find('.play-btn').click(function () {
                $element.find(".img-person").fadeOut('9000');
                $element.find(".play-btn").fadeOut('9000');
                $element.find(".player").fadeIn('9000');
            });
        };
    }

    angular.module('app', [])
        .directive('personPlayer', [personPlayerDirective]);
}());

Assuming your template is*:

<div person-player>
    <img class="img-polaroid img-person" ng-src="{{person.imgUrl}}">
    <div class="player">
        I'm a player.
    </div>
    <div class="btn-group">
        <button class="btn play-btn">
            <i class="icon-play"></i> Play
        </button>
        <button class="btn pause-btn">
            <i class="icon-pause"></i> Pause
        </button>
        <button class="btn stop-btn">
            <i class="icon-stop"></i> Stop
        </button>
    </div>
</div>

3) You could use CSS3 transitions with ng-click to achieve the same behavior without any jQuery DOM scripting...

New Template*:

<style>
    /* Twitter Bootstrap fade */
    .fade {
        opacity: 0;
        -webkit-transition: opacity 0.15s linear;
        -moz-transition: opacity 0.15s linear;
        -o-transition: opacity 0.15s linear;
        transition: opacity 0.15s linear;
    }
    .fade.in {
        opacity: 1;
    }
</style>

<div class="person-player">
    <img class="img-polaroid img-person fade {{imgPersonFade}}" ng-src="{{person.imgUrl}}">

    <div class="player fade {{playerFade}}">
        I'm a player.
    </div>
    <div class="btn-group">
        <button class="btn play-btn fade {{playBtnFade}}" ng-click="playing=true">
            <i class="icon-play"></i> Play
        </button>
        <button class="btn pause-btn">
            <i class="icon-pause"></i> Pause
        </button>
        <button class="btn stop-btn">
            <i class="icon-stop"></i> Stop
        </button>
    </div>
</div>

Controller*:

function DetailCtrl($scope, $routeParams, $http) {

    $scope.playing = false;

    // Update the *Fade scope attributes whenever the `playing` scope attribute changes
    $scope.$watch('playing', function (playing) {
        $scope.playerFade = playing ? 'in' : '';
        $scope.imgPersonFade = playing ? '' : 'in';
        $scope.playBtnFade = playing ? '' : 'in';
    });

    // Pull down a JSON file with my data to populate Angular template
    // ...

}

Anyway, like many of the new JS MV* application frameworks, Angular encourages you to "watch" for data/model changes rather than "listen" for DOM events. In fact, I recommend trying to use as little jQuery as possible until you've got the hang of this new paradigm shift.

* Code not tested :)



来源:https://stackoverflow.com/questions/17205596/controller-doesnt-work-after-url-change

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!