How can I disappear / in a view based on a SELECT change?

It's easy to do if we don't mind a blatant MVC violation, but since I'm trying to learn how to play well with angular, I've been tearing my hair out on harmless little things like this.

All I want is for it to div#thisShouldFade

disappear when a new thing is selected and then disappear with new data.

here's the html:

<body ng-app="MyApp">
  <div ng-controller="MyController as myCtrl">

    <select ng-model="myCtrl.currentThing" ng-options="object.name for object in myCtrl.things">
      <option value="">--choose a thing--</option>
    </select>

    <div id="thisShouldFade">{{myCtrl.currentThing.data}}</div>

  </div>
</body>

      

and javascript:

  angular.module("MyApp", [])

  .controller("MyController", function(){
    this.things = [
      { name: "Thing One",   data: "This is the data for thing one" },  
      { name: "Thing Two",   data: "This is the data for thing two" },  
      { name: "Thing Three", data: "This is the data for thing three" }
    ];

    this.currentThing = null;
  })

      

and plunk:

http://plnkr.co/edit/RMgEOd6nrT9lFQlslDR0?p=preview

I've tried a bunch of different approaches using ngAnimate to set classes with CSS transitions, but the main problem is that the model changes instantly as it is attached to SELECT

.

Does anyone have a good angular-fax strategy? I'd rather leave jQuery aside. However, here's a jQuery plunk that shows the desired effect:

http://plnkr.co/edit/SIFZI95Xy5IzgOQN0qVU?p=preview

+3


source to share


2 answers


Here's a hacky way to get the desired effect with transition delays and ng-repeat

. This is somewhat imperfect because there is a delay in going from selection to selection equal to the transition delay:



angular.module("MyApp", ['ngAnimate'])

.controller("MyController", function() {
  this.things = [{
    name: "Thing One",
    data: "This is the data for thing one"
  }, {
    name: "Thing Two",
    data: "This is the data for thing two"
  }, {
    name: "Thing Three",
    data: "This is the data for thing three"
  }];

  this.currentThing = [];
})
      

.animate {
  position: absolute;
  transition: all 0.5s;
}
.animate.ng-enter {
  opacity: 0;
}
.animate.ng-enter-active {
  opacity: 1.0;
  transition-delay: 0.4s;
  -webkit-transition-delay: 0.4s;
}
.animate.ng-leave {
  opacity: 1.0;
}
.animate.ng-leave-active {
  opacity: 0;
}
      

<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.16/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.16/angular-animate.min.js"></script>

<body ng-app="MyApp">
  <div ng-controller="MyController as myCtrl">
    <select ng-model="myCtrl.currentThing[0]" ng-options="object.name for object in myCtrl.things">
      <option value="">--choose a thing--</option>
    </select>
    <div ng-repeat="thing in myCtrl.currentThing" class="animate">{{thing.data}}</div>
  </div>
</body>
      

Run codeHide result


+1


source


Usually when you want to do something that affects the DOM, you create a directive.

I've made a very simple example of a directive to show how this can be done; http://jsfiddle.net/9ydqvzms/ . This example expects a variable called show to be created in the controller

$scope.show = {
    data: null
};

      

of course this can be resolved with the correct scoping in the directive or with some callbacks.



app.directive('optionFader', function () {
    return {
        link: function link(scope, element, attrs) {
            scope.$watch(attrs.optionFader, function (newValue, oldValue) {
                if (oldValue == newValue && newValue === undefined) return;

                var qelem = $(element);
                if (!scope.show.data) {
                    // if we have no previous value, fade in directly
                    qelem.fadeOut(0);
                    scope.show.data = newValue;
                    qelem.fadeIn(1000);
                } else {
                    qelem.fadeOut(1000, function () {
                        if (newValue) {
                            scope.show.data = newValue;
                            // we are outside of the digest cycle, so apply
                            scope.$apply();
                        }
                        qelem.fadeIn(1000);
                    });
                }
            });
        }
    };
});

      

Basically a directive listens for changes for some value, is set in currentThing.data

the example below, and then sets a different scope value show.data

, the actual value displayed.

Then you can apply this to your HTML with the attribute

<div id="thisShouldFade" option-fader="currentThing.data">{{show.data}}</div>

      

+1


source







All Articles