AngularJS Edit-In-Place Directive
by GlobalDomestic
HTML
<script src="http://code.angularjs.org/1.2.5/angular.js"></script>
<script src="http://code.angularjs.org/1.2.5/angular-sanitize.js"></script>
<div ng-controller="MyCtrl">
<input-edit-in-place ng-model="myModel.foo" type="text" placeholder="Please enter something...">{{ myModel.foo }}<pre>{{ edit | json }}</pre></input-edit-in-place>
<br>
<input-edit-in-place ng-model="myModel.bar" type="textarea" placeholder="Please enter something..."><div ng-bind-html="myModel.bar | linky"></div></input-edit-in-place>
<hr>
<pre>myModel: {{ myModel | json }}</pre>
</div>
<!-- text.tmpl -->
<script type="text/ng-template" id="text.tmpl">
<input type="text" autofocus autocomplete="off" placeholder="{{ placeholder }}" ng-model="view.model" ng-keydown="keyDown( $event )">
</script>
<!-- textarea.tmpl -->
<script type="text/ng-template" id="textarea.tmpl">
<textarea autofocus placeholder="{{ placeholder }}" ng-model="view.model" ng-keydown="keyDown( $event )"></textarea>
</script>
<!-- template.tmpl -->
<script type="text/ng-template" id="template.tmpl">
<div class="input-edit-in-place">
<div ng-hide="view.edit" ng-dblclick="showEdit()" ng-transclude></div>
<div ng-show="view.edit" ng-include="type + '.tmpl'"></div>
</div>
</script>
CSS
.input-edit-in-place {
min-width: 100px;
min-height: 20px;
border: solid 1px red;
}
[placeholder]::-webkit-input-placeholder {
color: #a4a4a4;
font-style: italic;
}
[placeholder]:focus::-webkit-input-placeholder {
-webkit-transition: opacity 0.5s 5s ease;
transition: opacity 0.5s 5s ease;
opacity: 0;
}
JavaScript
var myApp = angular.module( 'myApp', [ 'ngSanitize' ] );
myApp.controller( 'MyCtrl', [ '$scope', function ( $scope ) {
$scope.myModel = {
foo: 'Boop',
bar: 'This is some longer text and a link to http://www.angularjs.com'
};
}]);
myApp.directive( 'inputEditInPlace', [ function inputEditInPlaceDirective() {
return {
scope: {
placeholder: '@',
type: '@',
model: '=ngModel'
},
restrict: 'E', // only activate on element attribute
templateUrl: 'template.tmpl',
replace: true,
transclude: true,
controller: function inputEditInPlaceController( $scope ) {
$scope.save = function save() {
$scope.model = $scope.view.model;
$scope.hideEdit();
};
$scope.keyDown = function keyDown( $event ) {
// Escape key
if ( $event.keyCode === 27 ) {
$scope.hideEdit();
}
else if ( ( $event.ctrlKey || $event.metaKey ) && $event.keyCode === 13 ) {
$scope.save();
}
};
$scope.hideEdit = function hideEdit() {
$scope.view.edit = false;
};
$scope.showEdit = function showEdit() {
$scope.view = {
model: $scope.model,
edit: true
};
};
}
};
}]);