Angular js - slide views but not home page - ng-animate - javascript

i'm using ng-animate to slide the app views, so each route slides own view , this is my simple code:
html:
<div ng-view ng-animate class="slide"></div>
css:
/*Animations*/
.slide{
left:0;
}
.slide.ng-enter{
transition:0.15s linear all;
position:fixed;
z-index:inherit;
left:-100%;
height:inherit;
}
.slide.ng-leave{
transition:0.15s linear all;
position:fixed;
z-index:9999;
right:0;
}
.slide.ng-leave-active{
transition:0.15s linear all;
position:fixed;
right:-100%;
left:100%;
}
.slide.ng-enter-active{
transition:0.15s linear all;
left:0;
position:relative;
}
Now, i'm wondering , is there anyway to exclude the home page (main "/" route) from sliding?
In other terms: Any way to exclude a route from ng-animate?

That's what ng-class is for.
You can set a application-wide variable $rootScope.path whenever path changes.
app.run(function ($rootScope, $location) {
$rootScope.$on("$locationChangeStart", function (event, next, current) {
$rootScope.path = $location.path();
});
});
Then, you decide to set your animation class by that variable
If you want to set class slide only if path is not /, do like this
<div ng-view ng-class="{slide: path !== '/' }"></div>
By doing this way, you don't need to touch any of your controller.
Full demo is here, http://plnkr.co/edit/rmu8oc7ycKzRaA2zv5JN?p=preview
By the way, this uses currant angularJS version, 1.2.7
------- Edit (animate after visit main page) ------
app.run(function ($rootScope, $location) {
$rootScope.$on("$locationChangeStart", function (event, next, current) {
if (!$location.path().match(/^\/?$/) && !$rootScope.mainVisitedOnce) {
$rootScope.mainVisitedOnce = true;
}
});
});
and
<div ng-view ng-class="{slide: mainVisitedOnce }"></div>
http://plnkr.co/edit/QpDFkdKH1kk6ZXy07G5X?p=preview

Demo http://plnkr.co/edit/sMUM48?p=preview
Explain
No need to create separate controller, directive or change any business logic. Just use .animation method to add conditional animation to .slide.
Listen to $routeChangeSuccess event on $rootScope. This is event will be triggered before animation start, so you have time to set toRoot and fromRoot flag accordingly. If target view is not a "/" view, a enable-animation class will be added to ng-view element, so css transition defined will be performed.
If target view if a "/" view, no animation will be performed.
HTML
<ng-view class="slide"></ng-view>
CSS
.slide {
position: absolute;
top: 0;
width: 100%;
}
.slide div {
margin: 10px;
background: red;
}
.slide.enable-animation.ng-enter,
.slide.enable-animation.ng-leave {
transition: all 10s;
z-index: 1;
}
.slide.enable-animation.ng-enter {
left: -100%;
opacity: 0;
}
.slide.enable-animation.ng-enter.ng-enter-active,
.slide.enable-animation.ng-leave {
left: 0;
opacity: 1;
}
.slide.enable-animation.ng-leave.ng-leave-active {
left: 100%;
opacity: 0;
}
JavaScript
app.animation('.slide', function($rootScope, $animate) {
var toRoot = false;
var fromRoot = false;
$rootScope.$on('$routeChangeSuccess', function(event, current, old) {
toRoot = (current.$$route.originalPath === '/');
fromRoot = (old.$$route.originalPath === '/');
});
return {
enter: function(element, done) {
if (!toRoot) {
element.addClass('enable-animation');
}
done();
},
leave: function(element, done) {
if (!fromRoot) {
element.addClass('enable-animation');
done();
} else {
// set 1000ms timeout to sync with CSS animation
// otherwise leaving ng-view element will be removed before entering ng-view is in position
setTimeout(done, 1000);
}
}
}
});
Update 1
If you just want to exclude a route only when the first time app loads, you basically don't have to do anything, just define your css animation like normal. The first loaded route won't trigger any animation.
Demo http://plnkr.co/edit/uRZyZA?p=preview

Borrowing from #allenhwkim, get path in your rootScope.
app.run(function ($rootScope, $location) {
$rootScope.$on("$locationChangeStart", function (event, next, current) {
$rootScope.path = $location.path();
});
});
Then have this as your element:
<div ng-view ng-animate ng-class="{slide: path !== '/' }"></div>
.slide will be added to your container element when the path being loaded isn't /.
Here's a working Plunker.

Why don't you simply add a root class like class="not-animated" and class="animated" to the controllers you don't want or want to be animated?
In this way you could use the .not-animated and .animated class to play with your animation in different controllers.
You can set your controller like this:
<body ng-controller="MainCtrl" ng-class='isAnimated'>
<div ng-controller="FirstCtrl" ng-class='isAnimated'>Foo</div>
<div ng-controller="SecondCtrl" ng-class='isAnimated'>Bar</div>
</body>
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.isAnimated = 'not-animated';
});
app.controller('SecondCtrl', function($scope) {
$scope.isAnimated = 'animated';
});
This will result in:
<body ng-controller="MainCtrl" ng-class="isAnimated" class="ng-scope not-animated">
<p class="ng-binding">Hello World!</p>
<div ng-controller="FirstCtrl" ng-class="isAnimated" class="ng-scope not-animated">Foo</div>
<div ng-controller="SecondCtrl" ng-class="isAnimated" class="ng-scope animated">Bar</div>
</body>
DEMO

You can build a controller that listens for route changes and sets a class accordingly. You will then be able to target the correct animation using CSS.
<body ng-controller="TranisitionCtrl" ng-class="currentRoute">
<div ng-view ng-animate></div>
</body>
app.controller('TranisitionCtrl', function($scope) {
$scope.$on('$routeChangeStart', function(ev, next, current) {
$scope.currentRoute = current.name;
});
});
Please note $routeChangeStart has been changed to $locationChangeStart for more recent versions of angular.
I've answered another similar question here Two different animations for route changes

One way to exclude a specific route from the animation is to use a JS animation wrapper that will take over setting of the animation class for your ng-view. You need one additional class to handle the non-animated ng-leave when you are going back to the non-animated route.
Here is a sample JS wrapper that check for a custom animate attribute in your route to decide if a route is animated or not:
app.animation('.slider', function($log, $route) {
return {
//call done when the animation is over
enter : function(element, done) {
if ($route.current.animate) {
element.addClass("slide ng-enter");
}
done();
},
leave : function(element, done) {
if ($route.current.animate) {
element.addClass("slide ng-leave");
} else {
// Need to add non-animated version of ng-leave
element.addClass("slide ng-leave-noanimation");
}
done();
}
}
});
Here is the working plunker:
http://plnkr.co/edit/ldCy9Cfz2lJWNuLzDIbp?p=preview

As far as i understand you, what you want is, that no animation happens if the user hits your site. But after that the animations should happen all the time. This is the shortest solution i know:
Use the module run method to disable all animations:
app.run(function($animate){
$animate.enabled(false);
});
In your controller that is bound to / reenable the animations, but delayed for one digest cycle:
.controller('rootController', function($timeout, $animate){
$timeout(function(){
$animate.enabled(true);
});
})

Related

Synchronizing css transition in directive with asynchronous action in parent controller

I'm trying to synchronize a css transition in a directive with web socket events in it's parent controller.
For example, here is a scenario: User clicks on a product that he wants to purchase, I send a message to websocket server - upon receiving a successful response, I need to animate the product moving to users purchase cart and when this animation is complete, I have to actually add the product to users cart (I don't have access to this cart inside the directive)
Below is the code I have so far. Consider the pink box as a purchasable product, and the blue boxes inside bordered box as purchased products. User can purchase new product by clicking the pink box.
(For demo purpose, I'm manually calling $scope.purchaseSuccess, in real scenario it'll be invoked by socket.io)
angular.module('test', [])
.controller('testCtrl', function($scope) {
$scope.products = [{}, {}, {}, {}];
$scope.purchased = [{}];
$scope.purchase = function() {
//emits socket io message here
$scope.purchaseSuccess($scope.products.pop());
//--^--- this is called manually for demo purpose
};
$scope.purchaseSuccess = function(product) {
//success event handler called by socket io
$scope.$broadcast('purchase-success', product);
};
$scope.$on('transition-end', function(product) {
$scope.purchased.push(product);
$scope.$apply();
});
})
.directive('testDir', function() {
return {
scope: {},
link: function(scope, element) {
$helper = element.find('.helper');
var temp; // used to cache the product received from controllers event
scope.$on('purchase-success', function(product) {
temp = product; // cache the product to be sent back after animation
$helper.removeClass('no-transition');
$target = $('.purchased .product:last');
$helper.position({
my: 'top left',
at: 'top right',
of: $target,
using: function(pos, data) {
var val = 'translate3d(' + (pos.left + data.element.width) + 'px,' + pos.top + 'px,0px)'
$(this).css('transform', val);
}
});
});
$helper.on('transitionend MSTransitionEnd webkitTransitionEnd oTransitionEnd', function() {
$helper.addClass('no-transition');
$helper.css('transform', 'translate3d(0%,0px,0px)');
scope.$emit('transition-end', temp);
});
}
};
});
.product {
height: 50px;
width: 50px;
border: 1px solid;
}
.stock {
position: relative;
height: 50px;
background: silver;
}
.stock .product {
position: absolute;
background: hotpink;
}
.stock .product.helper {
transition: transform 2s;
}
.purchased {
height: 60px;
margin-top: 50px;
border: 2px dotted;
}
.purchased .product {
display: inline-block;
margin: 5px;
background: dodgerblue;
}
.no-transition {
transition: none !important;
}
<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<script src="https://code.angularjs.org/1.4.8/angular.js"></script>
<div ng-app="test" ng-controller="testCtrl">
<div class="stock" data-test-dir data-purchase="purchase">
<div class="product helper no-transition">
</div>
<div class="product" ng-click="purchase()">
</div>
</div>
<div class="purchased">
<div class="product" ng-repeat="product in purchased">
</div>
</div>
</div>
This is the tiniest demo I was able to make, the actual thing has further complications like timers running within which user has to finish all purchases
So, basically:
User's click invokes scope method which emits event to socket server
Socket.io success event handler broadcasts an angular event
Directive receives this event, caches the received data in a
temporary variable and triggers the CSS transition
When the animation is complete, directive emits an event with the
cached data
Controller receives this event and acts upon the data.
But this doesn't seem right. Is there a way to avoid sending this data back and forth..? Maybe a better way to achieve this without all the event emissions..?
Side note: those who aren't familiar with socket io, please consider purchase as a method that sends an ajax request, purchaseSuccess as it's success handler which should trigger the animation, and upon completion of this animation I need to do some action in the controller scope.

How to make Angular ng-switch animate(enter/leave) in more than one way?

I write an angular directive called 'cardViewer', which can show images inside it with animation.
When you press "prev" button, image slides left. When you press "next" button, image slides right.
I try to do this with ng-switch, which only supports .ng-enter and .ng-leave animation class. But I need two ways to enter(enter from left and right), two ways to leave(leave to left and right).
So I try ng-class to solve this problem. I hope it can add toLeft class before it switch, so it can apply specific css animation.
But it seems not working properly. When I press "next" button twice, it works fine. but when I press "next", then press "prev", new image enter in right direction, but old image leave in wrong direction.
My directive template:
<h1>hahaha</h1>
<div>
<button ng-click='prev()'>prev</button>
<button ng-click='next()'>next</button>
</div>
<div>current Card Index: {{displayCard}}</div>
<div class="card-container" ng-switch="displayCard">
<img class="card"
src="http://i.imgur.com/EJRdIcf.jpg" ng-switch-when="1"
ng-class="{'toLeft': toLeft, 'toRight': toRight}"/>
<img class="card"
src="http://i.imgur.com/StaoX5y.jpg" ng-switch-when="2"
ng-class="{'toLeft': toLeft, 'toRight': toRight}"/>
<img class="card"
src="http://i.imgur.com/eNcDvLE.jpg" ng-switch-when="3"
ng-class="{'toLeft': toLeft, 'toRight': toRight}"/>
</div>
directive:
angular.module('app', ['ngAnimate'])
.directive('cardViewer', function() {
return {
templateUrl: 'cardViewer.html',
link: function(scope, element, attr) {
scope.toLeft = false;
scope.toRight = false;
scope.displayCard = 1;
//when press prev, card slide to left
scope.prev = function() {
scope.toLeft = true;
scope.toRight = false;
if (scope.displayCard == 1) {
scope.displayCard = 3
} else {
scope.displayCard -= 1;
}
};
//when press prev, card slide to right
scope.next = function() {
scope.toLeft = false;
scope.toRight = true;
if (scope.displayCard == 3) {
scope.displayCard = 1
} else {
scope.displayCard += 1;
}
};
}
}
});
css:
.card-container {
position: relative;
height: 500px;
overflow: hidden;
}
.card {
width: 100%;
position: absolute;
}
.card.ng-animate {
transition: 1s linear all;
}
.card.ng-enter.toLeft {
left: 100%;
}
.card.ng-enter-active.toLeft {
left: 0;
}
.card.ng-leave.toLeft {
left: 0;
}
.card.ng-leave-active.toLeft {
left: -100%;
}
.card.ng-enter.toRight {
left: -100%;
}
.card.ng-enter-active.toRight {
left: 0;
}
.card.ng-leave.toRight {
left: 0;
}
.card.ng-leave-active.toRight {
left: 100%;
}
Here is my plunker: cardViewer
What's wrong with my code? What's the right way to make ng-switch enter/leave in more than one way?
The problem is that ngSwitch is destroying the scope of the current image before ngClass has a chance to execute and change that image's class from toRight to toLeft (or vice versa) before the animation starts.
ngSwitch creates a new scope and executes at priority level 1200, while ngClass executes at priority level 0.
To make it work, you just need to update your next and prev methods so they set the displayCard property in a $timeout, after toLeft and toRight are set, so ngClass has an opportunity to act on the new toLeft/toRight settings before ngSwitch destroys that scope.
So your next method, for example, would look like this:
scope.next = function() {
scope.toLeft = false;
scope.toRight = true;
// need to do this in a $timeout so ngClass has
// chance to update the current image's class based
// on the new toLeft and toRight settings before
// ngSwitch acts on the new displayCard setting
// and destroys the current images's scope.
$timeout(function () {
if (scope.displayCard == 3) {
scope.displayCard = 1
} else {
scope.displayCard += 1;
}
}, 0);
};
Here's a fork your plunk showing it working. Open the console to see log messages for when ngClass adds your classes and ngSwitch destroys and creates the scopes.
I left your original "next" and "prev" buttons there and just added "next (fixed)" and "prev (fixed)" buttons so you can compare the log messages and see how, using the original buttons, ngSwitch destroys the scope before ngClass executes, while in the fixed versions ngClass executes before ngSwitch destroys the scope.

AngularJS: $rootScope:infdig error when calling a ng-style function inside ng-repeat

I'm trying to build an animation on some phrases that will be displayed on the site main page, in a random position and with fade and translate effects.
I would achieve this using ng-style attribute inside an ng-repeat attribute and setting the ng-style value calling a JavaScript function defined inside the HomeController.
Using this approch cause angular to throw the exception: $rootScope:infdig error 10 $digest() iterations reached. Aborting! Watchers fired in the last 5 iterations
I read so much about this but no solution has solved my case.
Anyone could help me?
Here is a part of index.html:
<div class="phrasesContainer" animate-phrases="">
<h3 class="flying-text" ng-repeat="phrase in Phrases" ng-style="getTopLeftPosition()">{{phrase}}</h3>
</div>
Here is the controller function:
$scope.getTopLeftPosition = function() {
var top = randomBetween(10, 90);
var left = getRandomTwoRange(5, 30, 70, 80);
return {
top: top + '%',
left: left + '%'
};
}
Here is a demo: http://plnkr.co/edit/8sYks589agtLbZCGJ08B?p=preview
#Hieu Le hinted to the problem, but your issue is that since you are always returning a random position in your getTopLeftPosition function, angularjs digest loop will get called every time to actually propagate the changes to the watchers. This caused it to keep running over and over.
What you can do is to pre-calculate your random positions and then use that in your html.
For example, in your activate function you can do something like this:
function activate() {
$scope.Phrases = ["Phrase 1", "Phrase 2", "Phrase 3", "Phrase 4", "Phrase 5", "Phrase 6"];
$scope.PhrasesAndPositions = $scope.Phrases.map(function(phrase){
return {
phrase: phrase,
position: getTopLeftPosition()
}
});
}
And then you can change your html to something like this:
<div class="phrasesContainer" animate-phrases="">
<h3 class="flying-text" ng-repeat="pap in PhrasesAndPositions" ng-style="pap.position">{{pap.phrase}}</h3>
</div>
Here is the working plunk with my changes: http://plnkr.co/edit/FD9hYX9Q5wUkW2q7y86M?p=preview
Here's a solution where I moved your style generation into the directive. The position is being set right before showing the element. Since this is a CSS change, I modified the styling as well so that the position does not transition.
Here's the directive. The code I've excluded has not been changed:
app.directive('animatePhrases', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
setTimeout(function() {
...
}, 1000);
function changeText() {
var currentActive = $('.phrasesContainer .active');
var nextActive = currentActive.next();
currentActive.toggleClass('active');
if (nextActive.length == 0)
nextActive = $('.phrasesContainer .flying-text').first();
nextActive.css(getTopLeftPosition()); // Add this
nextActive.toggleClass('active');
setTimeout(changeText, 5000);
}
function getTopLeftPosition() {
...
}
function getRandomTwoRange(firstStart, firstEnd, secondStart, secondEnd) {
...
}
function randomBetween(min, max) {
...
}
}
};
});
CSS:
.flying-text {
transition: opacity 2s ease-in-out, margin 2s ease-in-out;
position: absolute;
opacity: 0;
font-size: 1.5em;
}
In your HTML, simply remove the ng-style.
Plunker: http://plnkr.co/edit/bZB3A5hD7Bc4r4pp1g7V?p=preview
this way you can manger your ng-style
$scope.getTopLeftPosition = function() {
$scope.top = randomBetween(20, 90);
$socpe.left = getRandomTwoRange(5, 30, 70, 80);
}
function getRandomTwoRange(firstStart, firstEnd, secondStart, secondEnd) {
var isLower = (Math.random() * 2) < 1;
if (isLower)
return randomBetween(firstStart, firstEnd);
else
return randomBetween(secondStart, secondEnd);
}
function randomBetween(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
<body>
<div ng-controller="HomeController">
<div class="row" style="height:100%">
<div class="phrasesContainer" animate-phrases="">
<h3 class="flying-text " ng-repeat="phrase in Phrases" ng-style="{ 'top' : top, 'left' : left }">{{phrase}}</h3>
</div>
</div>
</div>
I think the problem is that you cannot bind ng-style like that. It thinks that it needs to call getTopLeftPosition constantly.
I got it to kind of work here. The timing is a bit off but there are no more errors. Here I used $interval to repeat things:
Please view it here: http://plnkr.co/edit/B4iMZXMvZFoYMCKNvVrc?p=preview
$scope.phrase_style = getTopLeftPosition();
function change_phrase_style() {
$scope.phrase_style = getTopLeftPosition();
}
function start_interval() {
change_phrase_style();
$interval(function(){
change_phrase_style();
}.bind(this), 5000);
}
setTimeout(start_interval, 1000);
This might be related as well: angularjs infinite $digest Loop when no scope changes

How do I make angular-ui-layout stay within its container if it's in an angular view?

The problem is that internally (see .stretch CSS class), angular-ui-layout uses absolute positioning.
But that can be overridden, so it might work to just make it relative and set heigth to 100%:
<div style="height:100%; position: relative;">
<div ui-layout >...</div>
</div>
However, that doesn't work if it is in a directive in an angular view, it doesn't exist until it has been generated and probably can't say what 100% is at that point. Unless you hard-code height:400px, which isn't very flexible.
What to do?
The solution I chose (actually written in typescript but for the quickie I did not use any tricks) was to:
1 . Create a resize function that subtracts all other elements:
var resizeNodes=function() {
$("#nodesContainer").height($(window).height() - $("#footerDiv").height() - $("#menuDiv").height())
};
2 . Associate the route with a controller:
app.config(($routeProvider) => {
$routeProvider
.when('/admin', {
templateUrl: 'views/admin.html',
controller: "AdminCtrl"
})
...other routes ....
})
.otherwise({
redirectTo: '/'
});
});
3 . Create the controller, and in it first call the resize function on initialization, and then connect a listener to the window.resize function:
app.controller('AdminCtrl', ["$scope", "$timeout", function($scope, $timeout) {
// Wait for all angular stuff to be done.
$timeout(function () {
// Set height initially
resizeNodes();
// Add a watch on window.resize callback
$(window).resize(function(){
resizeNodes();
})
});
}]);

Auto growing textarea in ionic

I am trying to add an autogrowing textarea to my app but for some reason it is not working. The module that I am using is https://github.com/tagged/autogrow (it was recommneded on the ionic forum)
The answer above does not shrink - here is an improved version:
https://codepen.io/benshope/pen/xOPvpm
angular.module('app').directive('expandingTextarea', function () {
return {
restrict: 'A',
controller: function ($scope, $element, $attrs, $timeout) {
$element.css('min-height', '0');
$element.css('resize', 'none');
$element.css('overflow-y', 'hidden');
setHeight(0);
$timeout(setHeightToScrollHeight);
function setHeight(height) {
$element.css('height', height + 'px');
$element.css('max-height', height + 'px');
}
function setHeightToScrollHeight() {
setHeight(0);
var scrollHeight = angular.element($element)[0]
.scrollHeight;
if (scrollHeight !== undefined) {
setHeight(scrollHeight);
}
}
$scope.$watch(function () {
return angular.element($element)[0].value;
}, setHeightToScrollHeight);
}
};
});
This will transform all your textareas to grow/shrink.
Hope that helps!
I wrote a very simple directive that works with Ionic 2 and ion-textarea. Here it is:
import { Directive, HostListener, ElementRef } from "#angular/core";
#Directive({
selector: "ion-textarea[autoresize]" // Attribute selector
})
export class Autoresize {
#HostListener("input", ["$event.target"])
onInput(textArea: HTMLTextAreaElement): void {
this.adjust();
}
constructor(public element: ElementRef) {
}
ngOnInit(): void {
this.adjust();
}
adjust(): void {
let ta = this.element.nativeElement.querySelector("textarea");
ta.style.overflow = "hidden";
ta.style.height = "auto";
ta.style.height = ta.scrollHeight + "px";
}
}
Here is a gist: https://gist.github.com/maxt3r/2485356e91a1969bdb6cf54902e61165
EDIT: Look at the gist for other suggestions from other people.
I found a much more better way to do this without using any other third party library or directive.
$scope.updateEditor = function() {
var element = document.getElementById("page_content");
element.style.height = element.scrollHeight + "px";
};
Then simply adding ng-keypress="updateEditor()" to the textarea would do the job.
<textarea ng-keypress="updateEditor()" ng-model="bar"> </textarea>
I Hope this helps others who might face this problem in the future.
Update: Here is a codepen for this: http://codepen.io/kpourdeilami/pen/KDepk
Update 2: Use the snippet provided by #benshope
Update 3: If you're on Ionic/Angular 2, use the answer provided by "Max Al Farakh"
Try Angular-Elastic. It is an angular directive built to auto-expand a textarea. Use bower to install it.
bower install angular-elastic
add it to your project, then you can use it as an attribute
<textarea msd-elastic ng-model="foo"> </textarea>
or as class
<textarea class="msd-elastic" ng-model="bar"> </textarea>
From Ionic 4.4 it's built-in, see the autoGrow property:
TextArea#Properties
<ion-textarea auto-grow="true" rows="1"></ion-textarea>
Do you mean vertically auto-growing? I tried this:
<textarea ng-model='doc.description'
rows='{{doc.description.length/50 + 1}}'
cols='50'></textarea>
Kinda hackish, but after having determined an expected column length, lets define the row length based on the length of the inputed text. It starts growing vertically when I start typing! (no scrolling/out of view text).
With ionic-5 , there is an option called auto-grow, set it to true in your view.
In css, set min-height, max-height, to control the text grow.
ion-textarea {
min-height: 100px;
max-height: 200px;
}
Also, after the above fix, if you get some odd behaviour with placeholder text, add below inside the ion-textarea
::ng-deep textarea {
min-height: 100px;
}
If it can serve someone, I changed a little bit benshope's solution since I needed the textarea to grow even when user do a carriage return.
So instead of listening to the changes on the input value (which didn't always fire when doing a carriage return) I listent the input event on the textarea.
(function () {
'use strict';
angular
.module('app')
.directive('expandingTextarea', expandingTextarea);
function expandingTextarea() {
return {
restrict: 'A',
controller: function ($scope, $element, $attrs, $timeout) {
$element.css('min-height', '0');
$element.css('resize', 'none');
$element.css('overflow-y', 'hidden');
setHeight(0);
$timeout(setHeightToScrollHeight);
function setHeight(height) {
$element.css('height', height + 'px');
$element.css('max-height', height + 'px');
}
function setHeightToScrollHeight() {
console.log('set height');
setHeight(0);
var scrollHeight = angular.element($element)[0]
.scrollHeight;
if (scrollHeight !== undefined) {
setHeight(scrollHeight);
}
}
angular.element($element)[0].addEventListener("input", setHeightToScrollHeight);
}
};
}})();
juste install :
bower install angular-elastic or
npm install angular-elastic;
then import the elastic.js file in your index.html like this
<script src="js/elastic.js" type="text/javascript"></script>
the after that inject it in you angular module like this:
angular.module('yourApp', ['monospaced.elastic']);
the after that in your html file, in your footer-bar do like this:
<ion-footer-bar style="height: auto; overflow: visible !important"><textarea rows="1" msd-elastic ng-model="myMsg">
</textarea>

Categories