我有一个插入卡片的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的不同字段中?我注意到序列化的一些内容,但我不知道它在我的情况下意味着什么!
提前非常感谢你!
答案 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>