Reputation: 25
I've got an irritating problem with data binding using ng-model
and button
.
The principle of operation of my site:
projects
(loaded from external .json file).Edit
which displays a modal
containing some <input type="text"
filled with relevant data about project (like project.name
, project.date
etc.)value
of input is equal to object data (text-input called Name
will contain project.name
etc.)Save
button and confirm the operation (confirm(sometext)
is okay).
Closing the modal, not clicking the button or pressing cancel
on confirmation box should prevent data from being updated.project.name
is "Project2" and I modify it by adding 3 numbers resulting in "Project2137"), closing modal and opening it again should result in "Project2" text inside input (because object wasn't modified, only input)So far I understand that single text input should look like this
<input type="text" id="editName" class="form-control" ng-model = "project.name">
Using ng-model
means that they are binded. That's what I know. However editing input means that object is updated as soon as I enter some data.
I tried to fiddle with ng-model-options
but I didn't find any possible solutions.
I tried to do it programmatically as well using
<input type="text" id="editName" class="form-control" value = {{project.name}}>
....
<button type="button" class="btn pull-right btn-primary btn-md" ng-click="edit(project)" data-dismiss="modal" >Save</button>
And function:
$rootScope.edit = function(project)
{
if(confirm("Are you sure to save changes?"))
{
project.name = angular.element(document.getElementById('editName')).val();
// ...and so on with other properties
This solution is kinda close to what I wanted to achieve (object is updated only on confirm), but I faced another problem: input loads data from object only once at the beginning instead of each time the modal is opened which is against rule #5
Is there any way to fix this using either ng-model
bind or custom function? Or maybe there is some other, easier way?
--EDIT--
Here I don't have any problem with saving the data using a button, everything works well and clicking Save is reflected in a projects
list. (well until I hit a F5 key).
The problem is that input text is not properly binded to project
and that's what I want to fix.
Sample data (pseudocode)
project1.name = "Proj1" project2.name = "Proj2"
I click an Edit button on row #1
Save
button.10. Text input is "Proj1pezxde1" even though I didn't modify an object.
Text input should read data from object again (each time I open this modal) and thus display "Proj1"
That's the problem I want to fix. Sorry for being a little bit inaccurate.
Upvotes: 1
Views: 2688
Reputation: 9794
You can create a copy of the project object in modal controller and use this object to bind with the input element of the modal
$scope.copyProj = angular.copy($scope.project);
Assign the copy object properties to project only when save is clicked.
Upvotes: 1
Reputation: 3266
So , as I understand from your question , you need to update the project data only if it is saved. To do that you can maintain a copy of the actual object which get updated only it is saved like below :
Here we are using angular.copy(), which does a deep copy of the source object.
$scope.original = {name : "xyz"};
$scope.project = angular.copy(original);
//Call this when the user confirms to save , here we are replacing the
//original copy with the latest object that needs to be saved.
$scope.save = function () {
$scope.original = angular.copy($scope.project);
}
//Call this when closing the modal or clicking cancel or when losing
//focus, this will reset the changes to the original copy.
$scope.reset = function () {
$scope.project = angular.copy(original);
}
Upvotes: 0
Reputation: 2706
The simplest way to do this in my opinion is using a second object that is a copy of the project, and after confirmation applying the changes to the original project object.
For example, a simple "pseudo code" of a controller:
function MyCtrl($scope) {
$scope.projects = [...];
$scope.currentProject = null;
$scope.edit = function(project) {
$scope.currentProject = angular.copy(project); // This will create a copy so the changes in $scope.currentProject will not reflect.
// Open dialog with input bound to $scope.currentProject
if (confirm) {
// Assign all properties from currentProject to project
angular.extend(project, $scope.currentProject);
}
}
}
Upvotes: 0
Reputation: 242
As per my understanding after reading the provided descriptions, you have a list of projects, which is being used as in an repeater and you want to bind each projects data to a Text box and a Button.
Have you tried initializing your Projects object following way?
$scope.projects = [
{ 'name': 'proj1', 'id': '1' },
{ 'name': 'proj2', 'id': '2' }
];
Then you can do something like below to show your data
<div ng-repeat="project in projects">
<div>
<input type="text" class="form-control" ng-model = "project.name">
<button type="button" class="btn pull-right btn-primary btn-md" ng-click="edit(project)" data-dismiss="modal" >Save</button>
</div>
</div>
Upvotes: 0