Yehia A.Salam
Yehia A.Salam

Reputation: 2078

Angular best practices for splitting components

So i have this simple listing of system users (attached screenshot), client can edit the users or create new user and a new panel is displayed accordingly.

enter image description here enter image description here

What I'm doing is updating the different fields of the edit/create form depending on the user action. But since im coming from a Backbone background, the usual way I would do something like this is to create a new view, initialize it with a parameter indicating whether it's a create or edit mode, and then destroy this view when clicking on cancel/save changes/create user. But right now im just depending on angular event binding to update the same form elements, is this the proper way to do it in angular?

$scope.prepare_form = function (user_id) {

    if (user_id) {
        // edit mode
        var user = filterFilter($scope.users, { id: user_id })[0];

        $scope.fdata_create.name = user.name;
        $scope.fdata_create.email = user.email;
        $scope.fdata_create.role_name = user.role_name;
        $scope.fdata_create.id = user.id;
    } else {
        // create mode
        $scope.fdata_create.name = '';
        $scope.fdata_create.email = '';
        $scope.fdata_create.role_name = '';
        $scope.fdata_create.id = '';
    }


    $scope.form_create_open = true;

}

Upvotes: 3

Views: 703

Answers (2)

Michael Kang
Michael Kang

Reputation: 52837

I would reuse the same form, but bind to different models:

 app.controller('ctrl', function($scope){
        $scope.addUser = function(){
                 $scope.add= true;
                 $scope.user = {};
         };
        $scope.editUser =function(user){
                  $scope.add=false;
                  $scope.user ={};
                  angular.copy($scope.user, user);
         };

         $scope.onOK = function(user){
                   ...
                   angular.copy(user, $scope.user);
         };
});

HTML:

<div ng-controller="ctrl">
  <form>
         <input type ="text" ng-model="user.name" />
         <input type="text" ng-model="user.role" />
         <button ng-click="onOK(user)"> ok </button>
   </form>
  </div>

Upvotes: 2

levi
levi

Reputation: 22697

You should think based on Models rather than forms. You should create Teammate model with its sync methods, update, create, replace, etc. It is cleaner, here is example extract from this tutorial

Book html form.

<div ng-controller="BookController">  
    <div ng-style="{ backgroundImage: 'url(' + book.getImageUrl(100, 100) + ')' }"></div>
    Id: <span ng-bind="book.id"></span>
    <br/>
    Name:<input type="text" ng-model="book.name" />
    <br/>
    Author: <input type="text" ng-model="book.author" />
    <br/>
    Is Available: <span ng-bind="book.isAvailable() ? 'Yes' : 'No' "></span>
    <br/>
    <button ng-click="book.delete()">Delete</button>
    <br/>
    <button ng-click="book.update()">Update</button>
</div>

Book Model define as factory.

app.factory('Book', ['$http', function($http) {  
    function Book(bookData) {
        if (bookData) {
            this.setData(bookData):
        }
        // Some other initializations related to book
    };
    Book.prototype = {
        setData: function(bookData) {
            angular.extend(this, bookData);
        },
        load: function(id) {
            var scope = this;
            $http.get('ourserver/books/' + bookId).success(function(bookData) {
                scope.setData(bookData);
            });
        },
        delete: function() {
            $http.delete('ourserver/books/' + bookId);
        },
        update: function() {
            $http.put('ourserver/books/' + bookId, this);
        },
        getImageUrl: function(width, height) {
            return 'our/image/service/' + this.book.id + '/' + width + '/' + height;
        },
        isAvailable: function() {
            if (!this.book.stores || this.book.stores.length === 0) {
                return false;
            }
            return this.book.stores.some(function(store) {
                return store.quantity > 0;
            });
        }
    };
    return Book;
}]);

Book controller that uses Book Model

app.controller('BookController', ['$scope', 'Book', function($scope, Book) {  
    $scope.book = new Book();
    $scope.book.load(1);
}]);

If you want to update book name for example, you dont need to manually assign the new name because the Book's name instance is binded to ng-model attribute. To update it just only need call your update function from Book Factory.

$scope.book = new Book();
if(book_id){

    $scope.book.load(book_id);
    $scope.submit_book = $scope.book.update // submit_book function need to be triggered after submit the form. Here it
 }
else{
    $scope.submit_book = $scope.book.create // submit_book function need to be triggered after submit the form. Here it will create the book
 }

Upvotes: 2

Related Questions