2014-10-08 47 views
0

在我的模型中,我有一個需要綁定到幾個控件的字段。其中一個控件是一個文本框。文本框不應該直接編輯該字段,而應該允許用戶鍵入,然後提交更改或取消。如果發生任何其他操作,則應覆蓋文本字段中的任何更改。其中一個限制是,有其他UI組件會更改該值並且無法訪問本地作用域。如何在Angular中實現可取消的可編輯字段?

我實現了一個指令所需的行爲:http://jsfiddle.net/fLxjjmb7/3/

它按預期工作,但我覺得必須有一個更好的方式來做到這一點。有任何想法嗎?

<div ng-app="app" ng-controller="controller"> 
    <div>{{foo}}</div> 
    <button ng-click="increment()">increment</button> 
    <button ng-click="decrement()">decrement</button> 
    <br /> 
    <div shadow="foo"> 
     <input type="text" ng-model="foo" /> 
     <button ng-click="commit()">update</button> 
     <button ng-click="cancel()">cancel</button> 
    </div> 
</div> 
var app = angular.module('app', []); 

var controller = app.controller('controller', function ($scope) { 
    $scope.foo = 1; 
    $scope.increment = function() { ++$scope.foo; }; 
    $scope.decrement = function() { --$scope.foo; }; 
}); 

var directive = app.directive('shadow', function() { 
    return { 
    scope: true, 
    link: function(scope, el, att) { 
     scope.$parent.$watch(att.shadow, function (newValue) { 
      scope[att.shadow] = newValue; 
     }); 

     scope.commit = function() { 
     scope.$parent[att.shadow] = angular.copy(scope[att.shadow]); 
     }; 

     scope.cancel = function() { 
      scope[att.shadow] = angular.copy(scope.$parent[att.shadow]); 
     }; 
    } 
    }; 
}); 

回答

0

覺得你這個有點:)

查看複雜:

<div ng-controller="ShadowController"> 
    <h1>{{foo}}</h1> 

    <div> 
     <button ng-click="increment()">increment</button> 
     <button ng-click="decrement()">decrement</button> 
    </div> 

    <div> 
     <input type="text" ng-model="tempFoo" /> 
     <button ng-click="commit()">update</button> 
     <button ng-click="cancel()">cancel</button> 
    </div> 
</div> 

控制器:

.controller('ShadowController', function ($scope) { 
    $scope.foo = 1; 

    $scope.increment = function() { 
     ++$scope.foo; 
     $scope.cancel(); 
    }; 

    $scope.decrement = function() { 
     --$scope.foo; 
     $scope.cancel(); 
    }; 

    $scope.commit = function() { 
     $scope.foo = parseFloat($scope.tempFoo); 
    }; 

    $scope.cancel = function() { 
     $scope.tempFoo = $scope.foo; 
    }; 

    $scope.cancel(); 
}); 

一個更炫的方法是跟蹤的臨時價值變化,只有enabl如果在原始和臨時之間存在差異,則提交/取消按鈕。

查看:

<div ng-controller="ShadowControllerAdv"> 
    <h1>{{data.original}}</h1> 

    <div> 
     <button ng-click="increment()">increment</button> 
     <button ng-click="decrement()">decrement</button> 
    </div> 

    <div> 
     <input type="text" ng-model="data.edit" /> 
     <button ng-click="commit()" ng-disabled="!state.hasChanged">update</button> 
     <button ng-click="reset()" ng-disabled="!state.hasChanged">cancel</button> 
    </div> 
</div> 

控制器:

.controller('ShadowControllerAdv', function ($scope) { 
    var _dataWatcher; 

    $scope.data = { 
     original: 1 
    }; 

    $scope.state = { 
     hasChanged: false 
    }; 

    function _startWatcher() { 
     _dataWatcher = $scope.$watch('data.edit', function (newValue, oldValue) { 
      if (newValue !== oldValue) { 
       $scope.state.hasChanged = true; 
      } else { 
       $scope.state.hasChanged = false; 
      } 
     }, true); 
    } 

    function _stopWatcher() { 
     if (!_dataWatcher) { 
      return; 
     } 
     _dataWatcher(); 
    } 

    $scope.reset = function() { 
     _stopWatcher(); 
     $scope.data.edit = $scope.data.original; 
     $scope.state.hasChanged = false; 
     _startWatcher(); 
    } 

    $scope.commit = function() { 
     _stopWatcher(); 
     $scope.data.original = parseFloat($scope.data.edit); 
     $scope.reset(); 
    } 

    $scope.increment = function() { 
     $scope.data.original = $scope.data.original + 1; 
     $scope.reset(); 
    }; 

    $scope.decrement = function() { 
     $scope.data.original = $scope.data.original - 1; 
     $scope.reset(); 
    }; 

    $scope.reset(); 
}); 
+0

好主意。我應該提到其他UI組件也可以改變它的值。他們無權取消或其他本地範圍功能。 – fixedpoint 2014-10-08 21:04:10

+0

好的,如果控制器外部的組件可以更改該值,那麼您可能希望將get/set邏輯放在工廠中。如果數據對象存儲在工廠中,則「get」方法將返回完整的數據對象,「set」將更改數據。原始 - 您應該是金手指。可能希望在控制器中添加另一個偵聽器,以跟蹤從外部對原始數據所做的更改,如果發生這種情況,請調用$ scope.reset()。 – 2014-10-08 21:19:02

相關問題