<!DOCTYPE html>
<html>
<head>
<link data-require="bootstrap-css@3.1.1" data-semver="3.1.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
<script data-require="angular.js@1.2.17" data-semver="1.2.17" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.17/angular.min.js"></script>
<script data-require="jquery@*" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script data-require="bootstrap@3.1.1" data-semver="3.1.1" src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app='dynamicEditor'>
<div ng-controller='testCtrl'>
<div ng-repeat='item in items' item-editor>
<form class='form-horizontal'>
<div class='form-group'>
<label for='name' class='col-md-2 control-label'>Name</label>
<div class='col-md-3'>
<input name='name' id='name' class='form-control' ng-model='item.name' />
</div>
</div>
<div class='form-group'>
<label for='phone' class='col-md-2 control-label'>Phone</label>
<div class='col-md-3'>
<input name='phone' id='phone' class='form-control' ng-model='item.phone' />
</div>
</div>
<div class='form-group'>
<label for='location' class='col-md-2 control-label'>Location</label>
<div class='col-md-3'>
<input name='location' id='location' class='form-control' ng-model='item.location' />
</div>
</div>
</form>
</div>
</div>
</body>
</html>
var app = angular.module('dynamicEditor', []);
app.controller('testCtrl', function($scope) {
$scope.items = [{
name: 'John',
phone: '123456789',
location: 'London'
}, {
name: 'Diana',
phone: '4567884552',
location: 'Berlin'
}, {
name: 'Sonja',
phone: '9879564652',
location: 'Amsterdam'
}];
});
app.directive('itemEditor', function($compile) {
this.find = function(elements, type, apply) {
angular.forEach(elements, function(elem) {
if (elem.nodeName == type) {
apply(elem);
}
find(elem.childNodes, type, apply);
});
};
return {
restrict: 'AE',
replace: true,
transclude: true,
template: '<div class=\'readonly-item\' ng-transclude></div>',
link: function(scope, element, attrs) {
scope.editing = '';
scope.reading = '';
scope.isEdit = true;
scope.element = element;
scope.switchForm = function() {
console.log(JSON.stringify(scope.item));
if (scope.isEdit) {
scope.element.html(scope.reading);
} else {
scope.element.html(scope.editing);
}
if (scope.element[0].onclick === null) {
scope.element[0].onclick = scope.switchForm;
}
scope.isEdit = !scope.isEdit;
$compile(scope.element.contents())(scope);
};
var tmp = element.clone();
scope.editing = tmp.html();
tmp = element.clone();
this.find(tmp, 'INPUT', function(elem) {
var repl = angular.element(elem);
var str = '<label ';
var data = '';
angular.forEach(repl[0].attributes, function(attr) {
if (attr.name == 'ng-model') {
data = '{{' + attr.value + '}}';
} else {
//str += attr.name + '="' + attr.value + '" ';
}
});
str += '>' + data + '</label>';
repl.replaceWith(str);
});
scope.reading = tmp.html();
console.log(scope.reading);
console.log(scope.editing);
scope.switchForm();
}
};
});
.readonly-item {
margin: 10px 5px 10px 5px;
padding: 15px 5px 5px 5px;
}
.readonly-item .form-group{
margin-left: 0;
margin-right: 0;
}
.readonly-item:hover {
border: 1px solid;
border-color: black;
}
.editing-item {
margin: 10px 5px 10px 5px;
padding: 15px 5px 5px 5px;
border: 1px solid;
border-color: black;
}
.editing-item .form-group{
margin-left: 0;
margin-right: 0;
}