简体   繁体   中英

AngularJS - animate div using changing scope variable

I'm new to angular. I want to animate a div body using ng-click on a ng-repeat element. This is what I have tried so far.

app.js

var app = angular.module( 'app', [] );

app.controller('appController', function($scope) {

    $scope.items = [
  {"id": "id1", "name": "Name 1"},
  {"id": "id2", "name": "Name 2"},
  {"id": "id3", "name": "Name 3"}
  ];

  $scope.selectedStyle = {"background-color": "blue", "color": "white"};
  $scope.selectedItem = $scope.items[0];

  $scope.selectItem = function(item) {
    $scope.selectedItem = item;
  }

});

app.html

<div ng-app="app" ng-controller="appController">
  <table class=table>
    <tbody>
      <tr ng-repeat="item in items" ng-click="selectItem(item)" ng-style="item.id === selectedItem.id && selectedStyle">
        <td>
          {{item.id}}
        </td>
      </tr>
    </tbody>
  </table>

  <div class="item-body">
    {{selectedItem.name}}
  </div>
</div>

What I wanted to do is add a fade-in transition effect to item-body div as the changing item. I searched the web, but I can't seem to find a solution. Please help.

JSFiddle - https://jsfiddle.net/lpsandaruwan/ot45qdno/14/

Animating the items themselves

You can do this by adding a class to the selected element using angular , and managing the transition using css transitions .

This way, there's no need for $scope.selectedStyle . We'll manage that in css.

So, the flow would be like so:

  1. When a user clicks, angular will add a selected class to the clicked element.
  2. css transition for the class item will handle the color changes for you (both for select and deselect).

Here's the code:

 var app = angular.module('app', []); app.controller('appController', function($scope) { $scope.items = [{ "id": "id1", "name": "Name 1" }, { "id": "id2", "name": "Name 2" }, { "id": "id3", "name": "Name 3" }]; $scope.selectedItem = $scope.items[0]; $scope.selectItem = function(item) { $scope.selectedItem = item; } }); 
 .item-body { color: red; } .item { cursor: pointer; transition: all 250ms linear; } .item.selected { cursor: default; background-color: blue; color: white; } 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="app" ng-controller="appController"> <table class=table> <tbody> <tr ng-repeat="item in items" ng-click="selectItem(item)" class="item" ng-class="{ 'selected': selectedItem === item }"> <td> {{item.id}} </td> </tr> </tbody> </table> <div class="item-body"> {{selectedItem.name}} </div> </div> 

Animating the item-body

if you want to animate the item-body on change, you can use a simple timeout to add and remove a class.

Also, you should know that there are some modules that you can use to achieve this (like this ).

Here is what I suggest:

  1. add a flag to let the item-body element know it needs to hide and show
  2. hook that flag to a class
  3. make that flag hide and show the element, similar to the transition we did before

 var app = angular.module('app', []); app.controller('appController', function($scope, $timeout) { $scope.items = [{ "id": "id1", "name": "Name 1" }, { "id": "id2", "name": "Name 2" }, { "id": "id3", "name": "Name 3" }]; $scope.selectedItem = $scope.items[0]; $scope.selectItem = function(item) { $scope.changeIsOn = true; $timeout(function() { $scope.selectedItem = item; $scope.changeIsOn = false; }, 250); } }); 
 .item-body { color: red; transition: opacity 250ms linear; } .item-body.changing { opacity: 0; } .item { cursor: pointer; transition: all 250ms linear; } .item.selected { cursor: default; background-color: blue; color: white; } 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="app" ng-controller="appController"> <table class=table> <tbody> <tr ng-repeat="item in items" ng-click="selectItem(item)" class="item" ng-class="{ 'selected': selectedItem === item }"> <td> {{item.id}} </td> </tr> </tbody> </table> <div class="item-body" ng-class="{ 'changing': changeIsOn }"> {{selectedItem.name}} </div> </div> 

Using ng-class, you could apply the animation class selectively based on the scope value, eg:

$scope.selectedStyle = false;

<tr ng-class="({'myClass':selectedStyle})" >

You can create a custom directive that watches a assigned model to your item-body div and when value is changed you can use animate service of angular.

In your html view change notice that I have added my custom directive

<div ng-app="app"  ng-controller="appController">
  <table class=table>
    <tbody>
      <tr ng-repeat="item in items" ng-click="selectItem(item)" ng-style="item.id === selectedItem.id && selectedStyle">
        <td>
          {{item.id}}
        </td>
      </tr>
    </tbody>
  </table>

  <div class="item-body" my-dir ng-model="myValue">
    {{selectedItem.name}}
  </div>
</div>

Remember to download angular-animate.js and add it to your solution.Important part to inject a 'ngAnimate' dependency in your module and add your custom directive as follows.

Before doing this add a class style

 .myClass
    {
         background-color: red;
          transition: all 1s;
          -webkit-transition: all 1s ease-in-out;
    }

Notice that I am applying $watch method to monitor variable

var app = angular.module('app', ['ngAnimate']);

        app.controller('appController', function ($scope) {

                        $scope.items = [
              { "id": "id1", "name": "Name 1" },
              { "id": "id2", "name": "Name 2" },
              { "id": "id3", "name": "Name 3" }
              ];

            $scope.selectedStyle = { "background-color": "blue", "color": "white" };
            $scope.selectedItem = $scope.items[0];

            $scope.selectItem = function (item) {
                $scope.selectedItem = item;
                $scope.myValue = item.name;

            }

        }).directive("myDir", function ($animate, $timeout) {
            return function (scope, element, attrs) {
                scope.$watch('myValue', function (newValue, oldValue) {

                    if (newValue != oldValue) {

                        $animate.addClass(element, "myClass").then(function () {
                            $timeout(function () { $animate.removeClass(element, "myClass"); });
                        });
                    }

                },true);
            }
        }); 

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