Edit in JSFiddle

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

mod.controller('MyController', ['$scope', '$window', function($scope, $window) {
    $scope.name="Vacation Labs";
    $scope.phone="99999 12345";
    $scope.save_name = function(new_value) {
        $window.alert('Asssume that we make an AJAX request to save the name, which succeeds');
        return true;
    $scope.save_phone = function(new_value) {
        $window.alert('Assume that we make an AJAX request to save the phone, which fails due to some validation error. Which means we DONT update the model');
        return false;

mod.directive('inPlaceEdit', function() {
    return {
        'restrict' : 'A',
        'scope' : {
            'model' : '=inPlaceEdit',
            'on_save' : '&onSave'
        // This can probably be abstracted out into a templateUrl
        'templateUrl' : 'in-place-edit.html',
        'replace' : true,
        'link' : function(scope, element, attrs) {
            scope.ui = {'mode' : 'view'};
            scope.save = function() {
                scope.on_save({'new_value' : scope.new_model});
            scope.$watch('model', function(m) {
                scope.new_model = angular.copy(m);
<div ng-app="MyModule" ng-controller="MyController">
    <script type="text/ng-template" id="in-place-edit.html">
            <div ng-show="ui.mode=='view'">{{ model }} <a href="" ng-click="ui.mode='edit'">edit</a></div>
            <div ng-show="ui.mode=='edit'">
                <input type="text" ng-model="new_model" />
                <button type="button" ng-click="save()">Save</button>
                <button type="button" ng-click="ui.mode='view'">Cancel</button>
    <p>Edit this field and hit save (mocks a successful save)</p>
    <div in-place-edit="name" on-save="save_name(new_value)"></div>
    <p>Edit this field and hit save (mocks a failed save)</p>
    <div in-place-edit="phone" on-save="save_phone(new_value)"></div>