IWI
IWI

Reputation: 1608

animate + ng-repeat in an elegant solution?

I have a list thats build with ng-repeat, and I am trying to animate the list as the elements change position.

I am trying to base the idea off of this codepen, however, I havent been doing to well at getting it to work.

What needs to happen is:

  1. User clicks pin
  2. if pin was grey (and is now red), the pinned item needs to go to the top of the list (within its filter range)
  3. if pin was red and is now grey, it needs to go under all the red pins within its range.
  4. There needs to be an animation of this happening where the user can see the new red pin going to its new place, and vice-versa, where the new grey pin goes to place.

If anyone could help me that would be awesome.

This is what I have been working with (JSFiddle)

Controller

angular.module('MyApp', ['ngAnimate'])
.controller('App', function($scope){
  $scope.myData = [{
    id: 1,
    historyContact: [
            {
                "date": "2017-05-30T04:00:00.000Z",
                "time": "12:12pm",
                "method": "Incoming",
                "direction": "Inbound",
                "result": "answered",
                "notes": "a",
                "pin": true,
                "_id": 1
            }, {
                "date": "2017-05-30T04:00:00.000Z",
                "time": "12:12pm",
                "method": "Incoming",
                "result": "answered",
                "direction": "Inbound",
                "notes": "b",
                "pin": false,
                "_id": 2
            }, {
                "date": "2017-05-30T04:00:00.000Z",
                "time": "12:12pm",
                "method": "Incoming",
                "result": "answered",
                "direction": "Inbound",
                "notes": "c",
                "pin": false,
                "_id": 3
            }
        ]
  }];

  $scope.noteClicked = function(note) {
        console.log("clicked", note)
        if (note.pin == true) {
                note.pin = false;
            } else {
                note.pin = true;
            }
  };




});

Template

<div ng-controller="App" >
  <p>
    <p>
      <div class="note-wrapper itemPin" ng-repeat="note in myData[0].historyContact | orderBy: ['-pin', '-date' ] track by note._id">
        <div class="contact-history-date-device-wrapper">
          <p class="contact-history-date-device-text">
            {{note.date | date:'MMMM dd, yyyy'}} - {{note.time}}
          </p>
        </div>
        <div class="chat-wrap">
          <p class="chat-identifier">
            {{note.method}} | {{note.direction}}
          </p>
          <p class="chat-identifier">
            Contact Result: {{note.result}}
          </p>
        </div>


        <div class="pin-container">
          <div >
            <div ng-if="note.pin == true" >
              <img class="pin" src="http://i.imgur.com/QdFPdjY.png" ng-click="noteClicked(note)">
            </div>
            <div ng-if="note.pin == false" >
              <img class="pin" src="http://i.imgur.com/nNpprk2.png" ng-click="noteClicked(note)">
            </div>
          </div>
        </div>

        <div class="contact-history-note-text-wrapper">
          <p class="contact-history-note-atext">
            {{note.notes}}
          </p>
        </div>



        <hr> 

      </div>
</div>

Styles

$font-stack:    'Roboto', sans-serif;
.metawrapper {
  position: relative;
}

.scrollbox-contact {
  width:100%;

  // no needed because #grid-container--ui-view has already overflow scroll param by kei
  /*
  overflow:auto;
  */
  overflow-x: hidden;

  height: 100%;
  position: absolute;
  padding-top: 50px; /* header height*/
  top: 0px;

}

.contact-history-header {
  background-color: #F8F8F8;
  height: 50px;
  width: 100%;
  position: absolute;
  top: 0px;
  left: 0px;
}

.header-title {
  font-family: $font-stack;
  font-size: 15px;
  color: #364350;
  font-weight: 400;
  text-align: left;
  line-height: 50px;
  letter-spacing: 1px;
  margin-left: 30px;
}


.pencil-icon {
  position: relative;
  margin-left: 20px;
  margin-top: 15px;
}

.contact-history-date-device-text {
  font-family: $font-stack;
  font-size: 16px;
  font-weight: 500;
  color: rgb(80, 92, 100);
  text-transform: capitalize;
}

.contact-history-date-device-wrapper {
  margin-top: 25px;
  margin-left: 25px;
  display: inline-block;
}

.contact-history-note-text-wrapper {
  height: auto;
  width: 80%;
  overflow: hidden;
  margin-left: 25px;
  display: block;
  position: relative;
  bottom: 5px;
  margin-top: 4px;
}

.contact-history-note-text {
  font-family: 'Lato', sans-serif;
  font-weight: 400;
  color: #505C64;
  // height: 14px;
}

.contact-history-horizontal-line {
  height: 1px;
  width: 90%;
  margin-left: 5%;
  margin-right: 5%;
  background-color: rgba(80, 92, 100, 0.1);
  margin-top: 20px;
  margin-bottom: 20px;
}

.contact-history-horizontal-line2 {
  height: 1px;
  width: 85%;
  margin-left: 5%;
  margin-right: 10%;
  background-color: rgba(80, 92, 100, 0.1);
  margin-top: 40px;
  margin-bottom: 30px;
}

.contact-history-button {
  width: 175px;
  height: 36px;
  border-radius: 3px;
  border: 1px solid;
  border-color: rgba(119, 119, 119, 0.4);
  position: relative;
  left: 75%;
  bottom: 20px;
}

// ANIMATION FOR PIN MOVEMENT
// like .list-item in the animation walkthough
.note-wrapper {
  &:after {
  clear: both;
  content: '';
  display: block;
  }
  &.ng-move {
   animation: list-sort-flip-top 0.4s ease-in;
   transform: translate(0, 100%);
   z-index: 2;
   & + .note-wrapper {
     transform: translate(0, -100%);
     z-index: -1;
   }
   &.ng-move-active {
     & + .note-wrapper {
       animation: list-sort-flip-bottom 0.4s ease-in;
     }
   }
 }
}

@keyframes list-sort-flip-top {
  0% {
    transform: rotate(0) translate(0, 100%) rotate(0);
  }

  50% {
    transform: rotate(45deg) translate(0, 50%) rotate(-45deg)
  }

  100% {
    transform: rotate(90deg) translate(0, 0) rotate(-90deg)
  }
}

@keyframes list-sort-flip-bottom {
  0% {
    transform: rotate(0) translate(0, -100%) rotate(0);
  }

  50% {
    transform: rotate(45deg) translate(0, -50%) rotate(-45deg);
  }

  100% {
    transform: rotate(90deg) translate(0, 0) rotate(-90deg);
  }
}

@keyframes list-sort-slide-top {
  0% {
    transform:translate(0, 100%);
  }

  75% {
    transform:translate(0, 100%);
  }

  100% {
    transform:translate(0, 0);
  }
}

@keyframes list-sort-slide-bottom {
  0% {
    transform: translate(0, -100%);
  }

  25% {
    transform: translate(100%, -100%);
  }

  75% {
    transform: translate(100%, 80%);
  }

  80% {
    transform: translate(90%, 60%) skew(-50deg, 1deg);
  }

  100% {
    transform: translate(0, 0) skew(0, 0);
  }
}
//END ANIMATIONB

.edit-note-wrapper {
  display: none;
  margin-left: 20px;
  margin-top: 20px;
  width: 100%;
}

.save-btn {
  left: 1% !important;
}

.edit-contact-history-button {
  width: 25%;
  height: 36px;
  border-radius: 3px;
  border: 1px solid;
  border-color: rgba(119, 119, 119, 0.4);
  display: inline-block !important;
  position: relative;

}

.chat-identifier {
  font-size: 14px;
  font-family: $font-stack;
  font-weight: 300;
  color: #505C64;
}

.chat-wrap {
  position: relative;
  left: 25px;
  top: 5px;
}

.pin-container {
  position: relative;
  left: 90%;
  bottom: 35px;
}

.who-wrote-this {
  position: relative;
  left: 25%;
  p {
    color: #3da5d9;
    font-weight: 500;
    font-family: $font-stack;
  }
}

.pin {
  cursor: pointer;
  cursor: hand;
}

.patient-info-blue88 {
  width: 160px;
  height: 40px;
  border: 1px solid;
  border-radius: 4px;
  color: white;
  background-color: #3DA5D9;
  border-color: #3DA5D9;
  position: relative;
  right: 6px;
  bottom: 60px;
  cursor: pointer;
  float: right;
  cursor: hand;
}

.itemPin {
  -webkit-transition: top 1s ease-out, opacity 1s;
    -moz-transition: top 1s ease-out, opacity 1s;
}

Upvotes: 1

Views: 86

Answers (1)

George Sharvadze
George Sharvadze

Reputation: 570

I've added position field with timestamp to control the note position, also please note the CSS classes for ng-move, ng-active and etc. You can modify this in order to make it more fancy

CSS:

.ng-enter {
  -webkit-transition: s;
  transition: 1s;
  margin-top: 100%;
}

.ng-enter-active {
  margin-top: 0;
}

.ng-leave {
  -webkit-transition: 1s;
  transition: 1s;
  margin-top: 0;
}

.ng-leave-active {
  margin-top: 100%;
}

.ng-move {
  -webkit-transition: 1s;
  transition: 1s;
  background: gold;
}

.ng-move-active {
  background: #fff;
} 

Here is the working fiddle:

Fiddle

Upvotes: 1

Related Questions