LocalStorage of contenteditable content(AngularJS)

时间:2013-10-16 18:42:19

标签: angularjs local-storage angularjs-directive web-storage

我有一个插入卡片的AngularJS小工具。 我的目标是将它们存储在本地。我为卡阵列工作了,但不是卡片内容,这是“满足” 你可以帮助我并给我一些最佳实践解决方案吗?

这是一个Plunker(在JS中)(红色大按钮删除localStorage。确保打开一个宽窗口):http://plnkr.co/edit/SlbWZ5Bh62MDKWViUsMr

这是我的代码(使用CoffeeScript。对于JS,请参阅上面的Plunker):

这是用户输入的标记

<div class="card card-{{ card.color }}">
    <header>
        <p class="points" contenteditable></p>
        <p class="number" contenteditable>#</p>
        <h2 class="customerName"  contenteditable>{{ card.customer.name }}</h2>
        <h3 class="projectName" contenteditable>Project Name</h3>
    </header>
    <article>
        <h1 class="task" contenteditable>Title</h1>
        <p class="story" contenteditable>Description</p>
    </article>
    <footer>
        <div class="divisions">
        <p class="division"></p>
        <button ng-click="deleteCard()" class="delete">X</button>
        </div>
    </footer>
</div>
<div class="card card-{{ card.color }} backside">
    <article>
        <h2 class="requirement">Requirements</h2>
        <p contenteditable></p>
    </article>
</div>

在这里,您可以看到我上面控制器中卡片阵列的localStorage设置:

Card = (@color, @customer) ->

        $scope.cards = []

        json = localStorage.getItem "cards"
        getCards = JSON.parse(json) if json?
        $scope.cards = $scope.cards.concat getCards if getCards?

        $scope.reset = ->
            localStorage.clear()

        $scope.save = ->
            cards = []
            for card in $scope.cards
                cards.push
                    color: card.color
                    customer:
                        name: card.customer.name

            localStorage.setItem "cards", JSON.stringify(cards)

        $scope.addCardRed = (customer) ->
            $scope.cards.push new Card("red", customer)
            $scope.save()

如何将用户输入存储在localStorage的不同字段中?我注意到序列化的一些内容,但我不知道它在我的情况下意味着什么!

提前非常感谢你!

2 个答案:

答案 0 :(得分:1)

您可以将ng-model指令与任何contenteditable字段一起使用,就像使用输入或textarea一样。因此,您应该只使用{{...}},而不是尝试使用ng-model大括号将模型绑定到视图,然后将您的可编辑DOM元素视为表单中的字段。 / p>

例如,在您的视图中:

<header ng-repeat="card in cards">
    <!-- These are just sample fields for the card object, but you can modify them -->
    <p class="points" contenteditable ng-model="card.points"></p>
    <p class="number" contenteditable ng-model="card.number"></p>
    <h2 class="customerName"  contenteditable ng-model="card.customer.name"></h2>
    <h3 class="projectName" contenteditable ng-model="card.projectName"></h3>
</header>

然后在您的控制器中,您可以使用$scope将模型附加到$scope.cards = $scope.cards.concat getCards if getCards?。这将双向绑定您的cards模型到控制器的范围。

然后在您的控制器中,要在LocalStorage中镜像模型数据,您可以使用以下内容自行完成:

在您的控制器中:

....
//  for example's sake
$scope.cards = [  // the cards array would look something like this
    {points: 0, number: 5, customer: {name: 'bob'}, projectName: 'myProj1'},
    {points: 1, number: 6, customer: {name: 'joe'}, projectName: 'myProj2'},
    {points: 2, number: 7, customer: {name: 'bill'}, projectName: 'myProj3'},
    {points: 3, number: 8, customer: {name: 'jerry'}, projectName: 'myProj4'}
];
....
// listen to all changes to the $scope.cards array
$scope.$watch('cards', function(newVal){
    var str = angular.toJson(newVal); // serialize the cards array into a string
    // NOTE: the 'someKey' string is the key that you'll use later to retrieve it back
    window.localStorage['someKey'] = str;  // store the serialized string in localStorage
}, true);
....

在上面的示例中,angular.toJson(newVal)将采用newVal变量(这只是对“最近更新的”卡片数组的引用),并将其序列化为JSON字符串(即{{ 1}}只是基本上包装了本地angular.toJson方法。为了将javascript对象放入JSON.stringify(),必须将其序列化为字符串,因为您只能将基元作为LocalStorage键中的值。

因此,LocalStorage会被放入newVal,看起来像这样:

localStorage

然后(只要您需要),您可以使用以下内容再次从"[{"points":0,"number":5,"customer":{"name":"bob"},"projectName":"myProj1"},{"points":1,"number":6,"customer":{"name":"joe"},"projectName":"myProj2"},{"points":2,"number":7,"customer":{"name":"bill"},"projectName":"myProj3"},{"points":3,"number":8,"customer":{"name":"jerry"},"projectName":"myProj4"}]" 检索cards数组:

localStorage

或者您可以使用库来执行序列化/保存,如下所示:https://github.com/grevory/angular-local-storage。我从来没有使用它,但它完全符合您的要求。

希望这有助于澄清一些事情。

更新:这超出了这个问题的范围,但是因为你问过。听起来你并没有理解var str = window.localStorage['someKey']; $scope.cards = angular.fromJson(str); ng-repeat指令的概念。这些可能是Angular中两个最着名(也是最广泛使用)的指令。通过组合这两个指令(如上面的视图示例),当用户编辑视图中的数据时,它会自动保持您的模型(即ng-model)和您的视图(即$scope.cards)同步。 <header>将“自动”为ng-repeat数组中的每个card创建一个新的标题元素(因此cards)。因此,当添加新卡或从卡阵列中移除卡时,Angular将根据需要添加或删除ng-repeat="card in cards"元素。然后,使用<header>contenteditable指令,Angular会将这些可编辑DOM元素的内容绑定到每张卡的值。通常ng-model与表单元素(即input / textareas / choices)一起使用,但它也可用于任何可编辑字段。将您的可编辑元素视为输入,然后仔细查看角度文档found here中的ng-model示例。这应该会有所帮助。

答案 1 :(得分:0)

现在我知道让我困惑的是什么!

我的卡片属性的双向绑定不适用于contenteditable。我删除了每个contenteditable属性,而不是p,h2等,我用输入标签替换了标签。这对我来说很好。

感谢您的耐心和出色的解释,@滕尼森特!而对于$ watch提示!我非常感谢你的帮助:)

这是我对Controller的解决方案:

angular.controller 'CustomerController', ($scope)   ->

    $scope.customers = [
        { name: "name1" }
        { name: "name2" }
        { name: "name3" }
    ]

    $scope.cards = []

    Card = (@color, @customer, @points, @number, @projectName, @story) ->

    $scope.$watch 'cards', ((newValue) ->
        string = angular.toJson(newValue)
        localStorage["cards"] = string
    ), true

    json = localStorage["cards"]
    parsedCards = angular.fromJson(json) if json?
    $scope.cards = $scope.cards.concat parsedCards if parsedCards?


    $scope.reset = ->
        localStorage.clear()
        sessionStorage.clear()

        $scope.cards = []

    $scope.addCardRed = (customer) ->
        $scope.cards.push new Card("red", customer)

这是我对标记的解决方案:

<div class="card card-{{ card.color }}">
    <header>
        <input class="points" contenteditable ng-model="card.points"></input>
        <input class="number" placeholder="#" contenteditable ng-model="card.number"></input>
        <input class="customerName"  contenteditable ng-model="card.customer.name"></input>
        <input class="projectName" placeholder="Projekt" contenteditable ng-model="card.projectName"></input>
    </header>
    <article>
        <input class="task" placeholder="Titel" contenteditable ng-model="card.task"></input>
        <textarea class="story" placeholder="Story" contenteditable ng-model="card.story"></textarea>
    </article>
    <footer>
        <div class="divisions">
            <p class="division"></p>
            <button ng-click="deleteCard()" class="delete">X</button>
        </div>
    </footer>
</div>
<div class="card card-{{ card.color }} backside">
    <article>
        <h2 class="requirement">Requirements</h2>
        <textarea class="requirements" placeholder="Aspects" contenteditable ng-model="card.requirements"></textarea>
    </article>
</div>