2013-10-16 101 views
0

我有一個插入卡片的小AngularJS工具。 我的目標是將它們存儲在本地。我爲卡片陣列工作過,但不是卡片內容,這是「contenteditable」 你能幫我解決這個問題,並給我一些最佳實踐解決方案嗎?Contenteditable內容的LocalStorage(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設置的卡ARR的標記唉,這是在我的控制器上面:

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的不同領域用戶的輸入?我聽說了一些關於序列化的內容,但我不知道這對我來說意味着什麼!

非常感謝你提前!

回答

1

您可以使用ng-model指令和任何contenteditable字段,就像使用輸入或textarea一樣。因此,不要試圖使用大括號將模型綁定到視圖,而應該只使用ng-model,然後將可編輯的DOM元素視爲它們是表單中的字段。

例如,在您的視圖:

<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字符串(即angular.toJson只是基本上包裝原生JSON.stringify()方法)。爲了將一個javascript對象放入LocalStorage,它必須被序列化爲一個字符串,因爲只能將基元作爲LocalStorage鍵中的值。

所以newVal將獲得投入localStorage看起來像這樣:

var str = window.localStorage['someKey']; 
$scope.cards = angular.fromJson(str); 

"[{"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"}]" 

再後來(只要你需要它),你可以從localStorage再次使用下面的檢索cards陣列

或者你可以使用庫來做這樣的序列化/保存:https://github.com/grevory/angular-local-storage。我從來沒有使用它,但它確實如你所願。

希望這有助於澄清一些事情。

更新:這超出了這個問題的範圍,但自從你問。這聽起來像你沒有掌握ng-repeatng-model指令的概念。這些可能是Angular中最着名(也是最廣泛使用)的兩個指令。通過結合這兩個指令(如上述視圖示例),當用戶編輯視圖中的數據時,它將自動使您的模型(即$scope.cards)和您的視圖(即<header>)保持同步。 ng-repeat將自動爲您的cards陣列(因此爲ng-repeat="card in cards")中的每個card創建一個新的標題元素。所以,當新的卡片被添加或從卡片陣列中移除卡片時,Angular會根據需要添加或刪除元素。然後,使用contenteditableng-model指令,Angular會將這些可編輯DOM元素的內容綁定到每個卡片的值。通常ng-model與表單元素(即輸入/文本區/選擇)一起使用,但它也可用於任何可編輯字段。想象你的可編輯元素就好像它們是一個輸入,然後從角度文檔found here<input ng-model="" />示例中長時間觀察。這應該有所幫助。

+0

我仍然不確定如何執行它。你能給我另一個提示嗎?我是否必須在Card對象或外部附加模型?你能否給我舉一個例子,說明我如何存儲我的內容?不知何故,我還沒有完全理解整個localStorage和序列化的工作原理: - /如果你能幫助我,我將非常感激!非常感謝您提前! – christophe

+1

我添加了很多更多的解釋,使我以前的答案更詳細。如果您仍然感到困惑,請告訴我。 – tennisgent

+0

你太棒了!感謝您的新回覆。現在我明白了很多。仍然會導致頭痛的是如何使用卡陣列propery,因爲有些數據已經存在,當我添加一張新卡時,並且在用戶放入某些東西后卡數組的某些數據會被添加。另外,卡數組你在上面填充它)首先是空的,對嗎?我的空卡陣列如何與客戶的已設定值一起玩? 至少我明白$ watch和存儲的東西,謝謝:) – christophe

0

現在我知道是什麼使我困惑!

我的卡屬性的雙向綁定不適用於contenteditable。我刪除了每個contenteditable屬性,而不是p,h2等,我用輸入標籤替換了標籤。這對我來說很好。

感謝您的耐心和您的精彩解說@tennisagent!對於$ watch提示!我真的很感謝你的幫助:)

這是我的控制器解決方案:

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> 
相關問題