2013-03-16 3 views
53

При использовании ng-repeat Что такое лучший способ редактировать контент?Angular JS - Edit In Place Редактирование содержимого

В моей идеальной ситуации добавлен день рождения - это гиперссылка, при ее нажатии будет отображаться форма редактирования - точно такая же, как текущая форма добавления с кнопкой обновления.

Live Preview (Plunker)

HTML:

<!DOCTYPE html> 
<html> 
    <head lang="en"> 
    <meta charset="utf-8"> 
    <title>Custom Plunker</title> 
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular.min.js"></script> 
    <script> 
     document.write('<base href="' + document.location + '" />'); 
    </script> 
    <script src="app.js"></script> 
    <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.2.0/css/bootstrap-combined.min.css" 
    rel="stylesheet"> 
    </head> 
<body ng-app="birthdayToDo" ng-controller="main"> 
    <div id="wrap"> 

     <!-- Begin page content --> 
     <div class="container"> 
     <div class="page-header"> 
      <h1>Birthday Reminders</h1> 
     </div> 
      <ul ng-repeat="bday in bdays"> 
       <li>{{bday.name}} | {{bday.date}}</li> 
      </ul> 

      <form ng-show="visible" ng-submit="newBirthday()"> 
      <label>Name:</label> 
      <input type="text" ng-model="bdayname" placeholder="Name" ng-required/> 
      <label>Date:</label> 
      <input type="date" ng-model="bdaydate" placeholder="Date" ng-required/> 
      <br/> 
      <button class="btn" type="submit">Save</button> 
     </form> 
     </div> 

     <div id="push"></div> 
    </div> 

    <div id="footer"> 
     <div class="container"> 
     <a class="btn" ng-click="visible = true"><i class="icon-plus"></i>Add</a> 
     </div> 
    </div> 
    </body> 

App.js:

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

app.controller('main', function($scope){ 

    // Start as not visible but when button is tapped it will show as true 

     $scope.visible = false; 

    // Create the array to hold the list of Birthdays 

     $scope.bdays = []; 

    // Create the function to push the data into the "bdays" array 

    $scope.newBirthday = function(){ 

     $scope.bdays.push({name:$scope.bdayname, date:$scope.bdaydate}); 

     $scope.bdayname = ''; 
     $scope.bdaydate = ''; 

    }; 
}); 
+0

Отвечает ли ваш вопрос на фактическую реализацию или дизайн интерфейса? –

+0

@Flek Предназначено для реализации дизайна интерфейса просто –

+0

Я приехал сюда, ища то, что вы хотите, но заметили ли вы, что вы повторяете элемент'ul 'вместо'li'? В результате у вас столько элементов 'ul', сколько неправильных. – adripanico

ответ

69

Вы должны положить форму внутри каждого узла и использовать ng-show и ng-hide для включения и отключения редактирование, соответственно. Что-то вроде этого:

<li> 
    <span ng-hide="editing" ng-click="editing = true">{{bday.name}} | {{bday.date}}</span> 
    <form ng-show="editing" ng-submit="editing = false"> 
    <label>Name:</label> 
    <input type="text" ng-model="bday.name" placeholder="Name" ng-required/> 
    <label>Date:</label> 
    <input type="date" ng-model="bday.date" placeholder="Date" ng-required/> 
    <br/> 
    <button class="btn" type="submit">Save</button> 
    </form> 
</li> 

Ключевыми моментами здесь являются:

  • Я изменил указательные ng-model в локальной области видимости
  • Добавлено ng-show в form, чтобы мы могли показать его во время редактирования
  • Добавил span с ng-hide, чтобы скрыть контент во время редактирования
  • Добавил ng-click, что может быть в любой другой элемент, который переключает editing в true
  • Изменено ng-submit для переключения editing в false

Вот ваш updated Plunker.

+0

Спасибо за отличный ответ :) У меня проблема, и, кажется, когда я редактирую, она также показывает форму добавления - потому что ее значение равно true –

+0

Если бы я правильно ответил на ваш вопрос, просто установите '$ scope.visible = false' в 'newBirthday()'. Это приведет к тому, что форма добавления исчезнет при добавлении элемента. –

+0

Спасибо большое :) –

25

Я искал встроенное решение для редактирования, и я нашел плункер, который казался многообещающим, но это не сработало для меня из коробки. После некоторых возиться с кодом я получил его работу. Престижность человеку, который сделал первоначальное усилие, чтобы закодировать этот кусок.

Пример можно посмотреть здесь http://plnkr.co/edit/EsW7mV?p=preview

Здесь идет код: шаблон

app.controller('MainCtrl', function($scope) { 

    $scope.updateTodo = function(indx) { 
    console.log(indx); 
    }; 

    $scope.cancelEdit = function(value) { 
    console.log('Canceled editing', value); 
    }; 

    $scope.todos = [ 
    {id:123, title: 'Lord of the things'}, 
    {id:321, title: 'Hoovering heights'}, 
    {id:231, title: 'Watership brown'} 
    ]; 
}); 

// On esc event 
app.directive('onEsc', function() { 
    return function(scope, elm, attr) { 
    elm.bind('keydown', function(e) { 
     if (e.keyCode === 27) { 
     scope.$apply(attr.onEsc); 
     } 
    }); 
    }; 
}); 

// On enter event 
app.directive('onEnter', function() { 
    return function(scope, elm, attr) { 
    elm.bind('keypress', function(e) { 
     if (e.keyCode === 13) { 
     scope.$apply(attr.onEnter); 
     } 
    }); 
    }; 
}); 

// Inline edit directive 
app.directive('inlineEdit', function($timeout) { 
    return { 
    scope: { 
     model: '=inlineEdit', 
     handleSave: '&onSave', 
     handleCancel: '&onCancel' 
    }, 
    link: function(scope, elm, attr) { 
     var previousValue; 

     scope.edit = function() { 
     scope.editMode = true; 
     previousValue = scope.model; 

     $timeout(function() { 
      elm.find('input')[0].focus(); 
     }, 0, false); 
     }; 
     scope.save = function() { 
     scope.editMode = false; 
     scope.handleSave({value: scope.model}); 
     }; 
     scope.cancel = function() { 
     scope.editMode = false; 
     scope.model = previousValue; 
     scope.handleCancel({value: scope.model}); 
     }; 
    }, 
    templateUrl: 'inline-edit.html' 
    }; 
}); 

Директива:

<div> 
    <input type="text" on-enter="save()" on-esc="cancel()" ng-model="model" ng-show="editMode"> 
    <button ng-click="cancel()" ng-show="editMode">cancel</button> 
    <button ng-click="save()" ng-show="editMode">save</button> 
    <span ng-mouseenter="showEdit = true" ng-mouseleave="showEdit = false"> 
    <span ng-hide="editMode" ng-click="edit()">{{model}}</span> 
    <a ng-show="showEdit" ng-click="edit()">edit</a> 
    </span> 
</div> 

Чтобы использовать это просто добавить воды:

<div ng-repeat="todo in todos" 
    inline-edit="todo.title" 
    on-save="updateTodo($index)" 
    on-cancel="cancelEdit(todo.title)"></div> 

UPDATE:

Другой вариант заключается в использовании для Xeditable готовую AngularJS:

http://vitalets.github.io/angular-xeditable/

4

Поскольку это общая часть функциональности, это хорошая идея, чтобы написать директиву для этого. Фактически, кто-то уже сделал это и открыл его. Я использовал editablespan библиотеку в one of my projects, и он отлично работал, очень рекомендуется.

7

Я изменил свой plunker, чтобы заставить его работать через angular-xeditable:

http://plnkr.co/edit/xUDrOS?p=preview

Это общее решение для редактирования инлайн - Вам creale гиперссылок с editable-text директивой , который переключается в <input type="text"> тег:

<a href="#" editable-text="bday.name" ng-click="myform.$show()" e-placeholder="Name"> 
    {{bday.name || 'empty'}} 
</a> 

На дату я использовал editable-date директива, которая переключается на html5 <input type="date">.