【问题标题】:Best practice to update values in the table using AngularJS使用 AngularJS 更新表中值的最佳实践
【发布时间】:2016-01-25 15:43:34
【问题描述】:

我正在尝试使用 AngularJS 创建 3 向绑定,以便动态更改表和 localStorage 中的值。我也在使用 jqueryUI 对话框窗口,我想在其中更新值,然后将其保存到表和 localStorage。在ng-model 指令的帮助下,我正在向对话框窗口填充值。然后在 accept 按钮上,我将值保存到 localStorage 和表中:

                data.name = $scope.dialogName;
                data.author = $scope.dialogAuthor;
                data.genre = $scope.dialogGenre;
                data.price = $scope.dialogPrice;

            self.book.name = $scope.dialogName;
            self.book.author = $scope.dialogAuthor;
            self.book.genre = $scope.dialogGenre;
            self.book.price = $scope.dialogPrice;

但我认为这是一个坏主意(此代码不起作用),必须有更好的方法来实现我的目标。谢谢。

在这个问题下面你可以找到codeSnippet,它可以让你理解我的代码。

books = [
  {
    "name": "Javascript",
    "author": "David Flanagan",
    "genre": "learning",
    "price": "100"
  },
  {
    "name": "PHP",
    "author": "Luke Welling",
    "genre": "learning",
    "price": "120"
  },
  {
    "name": "Learning JavaScript Design Patterns",
    "author": "Addy Osmani",
    "genre": "learning",
    "price": "400"
  },
  {
    "name": "Understanding ECMAScript 6",
    "author": "Nicholas C. Zakas",
    "genre": "learning",
    "price": "204"
  },
  {
    "name": "Programming JavaScript Applications",
    "author": "Eric Elliot",
    "genre": "learning",
    "price": "214"
  },
  {
    "name": "The C Programming Language",
    "author": "Brian W. Kernighan",
    "genre": "learning",
    "price": "514"
  },
  {
    "name": "Programming Pearls",
    "author": "Jon L. Bentley",
    "genre": "learning",
    "price": "114"
  },
  {
    "name": "Java Concurrency in Practice",
    "author": "Brian Goetz",
    "genre": "learning",
    "price": "140"
  }
]

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

app.controller('appCtrl', function ($scope, $http) {
    $scope.title = "Angular Books List";
    $scope.books = books;

    $scope.addNewTask = function () {
        $scope.books = JSON.parse(localStorage['table']);
        $scope.books.push({
            name: $scope.bookName,
            author: $scope.bookAuthor,
            genre: $scope.bookGenre,
            price: $scope.bookPrice
        });
        $scope.bookName = "";
        $scope.bookAuthor = "";
        $scope.bookGenre = "";
        $scope.bookPrice = "";
        localStorage.setItem("table", JSON.stringify($scope.books));

    };

    $scope.ShowConfirm = function () {
        if ( window.confirm("Are you sure?")) {
            var local = JSON.parse(localStorage['table']);
            for (var i = 0; i < local.length; i++) {
                if (local[i].name == this.book.name) {
                    local.splice(i, 1);
                    $scope.books.splice(i, 1);
                    console.log(local);
                    console.log(i);
                    localStorage.setItem("table", JSON.stringify(local));
                    break;
                }
            }
        } else {

        }
    };

    $scope.enableEditor = function(book){
        var self = this,
            data;
      
        $scope.selectedBook = book;
        $scope.dialogBook = angular.copy(book);


        $('#editDisplay').dialog({
            modal: true,
            resizable: false,
            width: 400,
            buttons: {
                Accept: function () {
                    $(this).dialog("close");
                  
                    angular.copy($scope.dialogBook,$scope.selectedBook);
                    localStorage.setItem("table", JSON.stringify($scope.books));

                },
                Cancel: function () {
                    $(this).dialog("close");
                }
            }
        });

    };

    $scope.predicate = 'name';
    $scope.reverse = false;
    $scope.order = function (predicate) {
        $scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
        $scope.predicate = predicate;
    };
});
.sortorder:after {
  content: '\25b2';
}
.sortorder.reverse:after {
  content: '\25bc';
}
.addBookInputs input {
  display: inline-block;
  width: 250px;
}
.addBookInputs {
  margin-bottom: 40px;
}
input::-webkit-outer-spin-button,
 input::-webkit-inner-spin-button {
   /* display: none; */
   -webkit-appearance: none;
   margin: 0;
 }
<link href="https://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>

<body ng-app="app">


<div class="container" ng-controller="appCtrl">
    <div class="page-header">
        <h1>
            {{title}}
        </h1>
    </div>
    <div class="col-xs-12 col-sm-12 col-md-3 col-md-offset-9 col-lg-3 col-lg-offset-9">
        <input type="text" class="form-control" ng-model="searchField" placeholder="search book...">
        <br>
        <br>

    </div>


    <div class="panel">
        <div class="addBookInputs">
            <input class="form-control" ng-model="bookName" placeholder="type name of the book"/>
            <input class="form-control" ng-model="bookAuthor" placeholder="type author of the book"/>
            <input class="form-control" ng-model="bookGenre" placeholder="type genre of the book"/>
            <input class="form-control" ng-model="bookPrice" placeholder="type price of the book" type="number"/>
            <span class="">
                <button class="btn btn-success" ng-click="addNewTask()">Add Book</button>
            </span>
        </div>



        <table class="table table-hover table-bordered table-">
            <thead>
            <tr>
                <th>
                    <a href="" ng-click="order('name')">Book Name</a>
                    <span class="sortorder" ng-show="predicate === 'name'" ng-class="{reverse:reverse}"></span>
                </th>


                </th>
                <th>
                    <a href="" ng-click="order('author')">Author</a>
                    <span class="sortorder" ng-show="predicate === 'author'" ng-class="{reverse:reverse}"></span>
                </th>
                <th>
                    <a href="" ng-click="order('genre') ">Genre</a>
                    <span class="sortorder" ng-show="predicate === 'genre'" ng-class="{reverse:reverse}"></span>

                </th>
                <th>
                    <a href="" ng-click="order('price')">Price</a>
                    <span class="sortorder" ng-show="predicate === 'price'" ng-class="{reverse:reverse}"></span>
                </th>


                <th>Delete?</th>
            </tr>
            </thead>
            <tbody>
            <tr ng-repeat="book in books | filter:searchField | orderBy:predicate:reverse" ng-hide="book.done">
                <td>
                    {{book.name}}
                </td>
                <td>
                    {{book.author}}
                </td>
                <td>
                    {{book.genre}}
                </td>
                <td>
                    {{book.price | currency}}
                </td>
                <td>
                    <button ng-click = "enableEditor(book)" class="btn btn-warning" > edit </button>
                    <button ng-click = "ShowConfirm()" class="btn btn-danger" > delete </button>
                </td>
                <!--<td>-->
                        <!--<span style="{{setStyle(book.done)}}">-->
                            <!--{{showText(book.done)}}-->
                        <!--</span>-->
                <!--</td>-->
            </tr>
            </tbody>
        </table>

        <div id="editDisplay" class="form-horizontal" style="display:none" title="editor">
            <div class="control-group">
                <label class="control-label">id</label>

                <div class="controls">
                    <input class="input-block-level form-control" type="number" disabled>
                </div>
            </div>

            <div class="control-group">
                <label class="control-label">name</label>

                <div class="controls">
                    <input class="input-block-level form-control" type="text" ng-model = "dialogBook.name">
                </div>
            </div>

            <div class="control-group">
                <label class="control-label">author</label>

                <div class="controls">
                    <input class="input-block-level form-control" type="text" ng-model = "dialogBook.author">
                </div>
            </div>

            <div class="control-group">
                <label class="control-label">genre</label>

                <div class="controls">
                    <input class="input-block-level form-control" type="text" ng-model="dialogBook.genre">
                </div>
            </div>
            <div class="control-group">
                <label class="control-label">price</label>

                <div class="controls">
                    <input class="input-block-level form-control" type="number" ng-model = "dialogBook.price">
                </div>
            </div>
        </div>
    </div>
</div>


</body>

【问题讨论】:

  • "this code doesn't work" 不是正确的问题描述。什么有效或无效?有什么错误吗?提供更多详情
  • 不完全确定您要达到的目标。您是否试图消除重复代码?如果是这样,请使用书籍对象而不是单个属性。您是否尝试确保每次更改时图书数组都会自动保存到本地存储中?如果是这样,$watchCollection 或 $watch 书籍数组并在检测到更改时保存它,或者使用 angular-localforage 并将数组直接绑定到 localstorage。如果您想澄清这些技术中的任何一种,请告诉我们。如果不是这些问题,也许澄清问题会有所帮助。
  • @Beartums 抱歉造成误解。我想要的只是使编辑功能成为可能,它将: 1. 将数据保存在本地存储中。 2.动态改变表格中的值。我实现了在本地存储中保存数据,但在页面重新加载之前我看不到表中的变化。所以问题是如何使它成为可能。

标签: javascript jquery angularjs jquery-ui


【解决方案1】:

@max,我想我明白了,但如果这没有帮助,请多多包涵。首先,为了清楚起见,我会在这里使用对象。使用 newBook 对象添加新书

    <div class="addBookInputs">
        <input class="form-control" ng-model="newBook.bookName" placeholder="type name of the book"/>
        <input class="form-control" ng-model="newBook.bookAuthor" placeholder="type author of the book"/>
        <input class="form-control" ng-model="newBook.bookGenre" placeholder="type genre of the book"/>
        <input class="form-control" ng-model="newBook.bookPrice" placeholder="type price of the book" type="number"/>
        <span class="">
            <button class="btn btn-success" ng-click="addNewTask()">Add Book</button>
        </span>
    </div>

然后,在控制器中,您只需要在初始设置期间获取本地存储中的数组值(另外,我认为您从本地存储中检索的语法是错误的)。在 Add() 函数中,我只需将新书添加到数组中,然后将数组保存到本地存储。

$scope.books = JSON.parse(localStorage.getItem('table'));

$scope.newBook = {};

$scope.addNewTask = function () {
    $scope.books.push(newBook);
    $scope.newBook = {};
    localStorage.setItem("table", JSON.stringify($scope.books));
};

对于编辑对话框,我将传递书籍对象 (book) 和书籍的 angular.copy (editBook)。然后,当编辑被批准(在 editBook 中)时,您应该能够 angular.copy(editBook,book) 而不破坏参考。您所做的更改应该出现在书籍中,然后您可以将它们保存到本地存储中。

这有帮助吗?

更新:编辑功能。 (我建议你学习AngularUI。JQuery 被认为是 Angular 应用程序的反模式)

首先,在 html 中,您应该将编辑按钮的 ng-click 属性更改为 ng-click="enableEditor(book)",以便将书籍引用传递给您的函数。那么函数可以是:

$scope.enableEditor = function(book){
    $scope.selectedBook = book;
    $scope.dialogBook = angular.copy(book)

    $('#editDisplay').dialog({
        modal: true,
        resizable: false,
        width: 400,
        buttons: {
            Accept: function () {
                $(this).dialog("close");
                $timeout(function() {
                    angular.copy($scope.dialogBook,$scope.selectedBook);
                    localStorage.setItem("table", JSON.stringify($scope.books));
                })
            },
            Cancel: function () {
                $(this).dialog("close");
            }
        }
    });
};

您需要像 $html 一样将 $timeout 传递给控制器​​(这允许 angular 从对话框中获取异步更改)。您还需要更改对话框的 html 以引用 dialogBook.name、dialogBook.genre 等。最后,价格输入字段中的“数字”类型将不起作用,因为您有小数点(我会只需将其更改为文本并单独进行验证)。

你可以找到一个工作小提琴here

【讨论】:

  • 哇!感谢您在我的桌子上添加新书的好例子。这是一个非常好的解决方案。而且非常简单)但是您能否更具体地描述 EDIT 功能。谢谢
  • @max,酷。很高兴它有帮助。我已经更新了您的编辑功能的答案——我不知道 jqueryUI,所以您可能需要查看概念而不是具体代码。
  • 在您推荐期间,我在上面的代码 sn-p 中进行了修复。但不幸的是,它不起作用。也许我做错了什么?
  • 再次对答案进行了更改以解释一些其他需要的更改。希望他们有所帮助。
  • 是的,这是标准做法。 Angular 不知道大多数异步更新,所以 $timeout 函数只是告诉它等到下一个摘要周期,以便观察者能够捕获它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多