Angular: Empty Fiddle

http://angularjs.org/

HTML

<script src="http://code.angularjs.org/angular-1.0.1.js"></script>
<div ng-controller="MyCtrl">
  Hello, {{name}}!
  <auto-expand-input />
</div>

<a href="#">Focusable link</a>

CSS

/* 
The burden is on you to make sure that the styles match so that 
when the textarea swaps in it's seamless
*/
input[type="text"],
textarea {
    width: 20%;
    padding: .3em;
    line-height: 1.5;
    border: 1px solid red;
    border-bottom-color: blue;
    background-color: burlywood;
    box-sizing: border-box;
    overflow: hidden;
    font-size: 2em;
    resize: none;
}

input[type="text"] {
    position: relative;
    z-index: 1;
    /* Uncomment this opacity when you're ready 
    opacity: 0;
    */
}

textarea {
    position: absolute;
    z-index: 0;
}

textarea:focus {
    z-index: 2
}

textarea:focus + input[type="text"] {
    opacity: 0;
}

JavaScript

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

myApp.directive('autoExpandInput', function() {
  return {
      restrict: 'E',
      replace: 'true',
      template: '' +
        '<div>' +
            '<textarea rows="1" tabindex="-1"></textarea>' +
            '<input type="text" value="{{inputValue}}" />' +
        '</div>',
      link: function(scope, elem, attrs) {
          elem.find('input').bind('focus', function (ev) {
              ev.target.tabIndex = -1;
              ev.target.previousSibling.focus();
          });
          elem.find('textarea').bind('blur', function (ev) {
              setTimeout(function () {
                  ev.target.nextSibling.tabIndex = 0;
              });
          })[0].oninput = function (ev) {
            var textarea = ev.target;
            scope.$apply(function() {
              scope.inputValue = textarea.value;
            });

            textarea.style.height = "";
            if (textarea.clientHeight < textarea.scrollHeight + 2) {
                textarea.style.height = textarea.scrollHeight + 2 + "px";
                textarea.nextSibling.style.height = textarea.scrollHeight + 2 + "px";
            }
        }
      }
  };
});

function MyCtrl($scope) {
    $scope.name = 'Superhero';
    $scope.inputValue = "";
}