我試圖構建一個小部件來呈現UI上的任意數據(JavaScript對象)。數據的模式由json schema文件定義。而且模型必須是雙向綁定的,因爲我想使用這個小部件來輸入/顯示數據。angularjs指令根據任意js構建小部件json模式對象
指令是否是正確的方法?有沒有人可以給我一些線索來實現這一目標?
我試圖構建一個小部件來呈現UI上的任意數據(JavaScript對象)。數據的模式由json schema文件定義。而且模型必須是雙向綁定的,因爲我想使用這個小部件來輸入/顯示數據。angularjs指令根據任意js構建小部件json模式對象
指令是否是正確的方法?有沒有人可以給我一些線索來實現這一目標?
是的,指令是正確的。你可以看到評論中提到的angular-schema-form
正在使用指令。
如果您想創建自己的指令。請看下面的演示或此jsfiddle。
帶註釋的例子可能不是最好的,因爲在那裏你不需要數據的雙向綁定。 但它應該給你一個想法如何可以工作。
代碼是如何工作的?
schema.items.properties
並創建ng-model
/ng-restrict
模板,並將其添加到模板中的所有綁定。$compile
服務正在將當前範圍添加到模板。與angular-schema-form
代碼相比,該演示可能非常基本,但它更易於理解,並且更易於根據需要進行修改。
angular.module('demoApp', [])
.controller('mainController', MainController)
.directive('awDisplayJsonView', DisplayJsonView)
.directive('awDateParser', DateParser);
/**
* Translates unix time stamp into readable dates
* from model/view & view/model
*/
function DateParser() {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModelController) {
ngModelController.$parsers.push(function(data) {
//convert data from view format to model format
return new Date(data).getTime(); //converted
});
ngModelController.$formatters.push(function(data) {
//convert data from model format to view format
return new Date(parseInt(data)).toUTCString(); //converted return UTC
});
}
}
}
function MainController() {
angular.extend(this, {
/*jsonView: {
"text": { // name of model
type: "input",
label: "Two way binded input",
}
},*/
jsonModel: [{
"id": 1,
"name": "Test User",
"text": "I am a comment.",
"date": "1435427542904",
}, {
"id": 2,
"name": "Antother User",
"text": "I am the second comment.",
"date": "1435427605064",
}],
jsonSchema: {
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Comments",
"type": "array",
"items": {
"title": "Comment",
"type": "object",
"properties": {
"id": {
"description": "The unique identifier for a comment.",
"type": "number",
"format": "hidden" // not sure if this is the right place
},
"name": {
"title": "Name",
"type": "string"
},
"text": {
"title": "Comment",
"type": "string"
},
"date": {
"title": "Date (format y/m/d hh:mm:ss GMT)",
"type": "string",
"format": "date-time"
}
},
"required": [
"id",
"name",
"text"]
}
}
});
}
function DisplayJsonView($compile) {
var templatesObj = {
string: function (hidden) {
return $('<input/>')
.attr('type', hidden)
.addClass('form-control');
},
checkbox: function (hidden) {
return $('<input/>')
.attr('type', hidden || 'checkbox')
.addClass('form-control');
},
number: function(hidden) {
return $('<input/>')
.attr('type', hidden)
.addClass('form-control');
}
};
function render(schema, model, index) {
var outTemplate = $(document.createDocumentFragment()),
tempTmpl, hidden; // temporary template, hidden input
angular.forEach(schema.items.properties, function (prop, key) {
//console.log(key, prop.type, prop.format, templatesObj[prop.type]);
hidden = prop.format == 'hidden'? 'hidden': null;
tempTmpl = templatesObj[prop.type](hidden); // get template based on type
tempTmpl.attr({
'ng-model':
'model[' + index + '].' + key, // add current model
'ng-required': schema.items.required.indexOf(key) != -1 // check if it is required
});
if (prop.format == 'date-time')
tempTmpl.attr('aw-date-parser', ''); // add directive if we have a date
outTemplate.append($('<div/>').addClass('form-group')
.append(!hidden ? $('<label/>').text(prop.title || key) : null) //add label if not hidden
.append(tempTmpl));
});
//console.log(model, outTemplate);
return outTemplate;
}
return {
restrict: 'EA',
scope: {
//view: '=', // angular schema form does implement this
model: '=',
schema: '='
},
template: '<div>{{schema |json:2}}</div>',
link: function (scope, element, attrs) {
var out = $('<form/>');
angular.forEach(scope.model, function(item, index) {
//console.log(item);
out.append(render(scope.schema, item, index));
});
var compiled = $compile(out)(scope);
//console.log(scope.model, scope.schema);
element.replaceWith(compiled);
}
};
}
DisplayJsonView.$inject = ['$compile'];
body {
padding: 0.5em;
}
.form-group {
padding-bottom: 0.25em;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.1/angular.js"></script>
<div ng-app="demoApp" ng-controller="mainController as ctrl">
<h3>Comments list with schema json directive</h3>
<form name="form" aw-display-json-view="" data-model="ctrl.jsonModel" data-schema="ctrl.jsonSchema" ng-cloak=""></form>
<div ng-cloak>
{{form|json}}
{{ctrl.jsonModel}}
</div>
</div>
感謝Awolf!似乎angular-schema-form可以爲我節省很多工作。我會花一些時間來研究它。 – ricky
存在已經是一個開源項目,處理這樣的事情:http://schemaform.io/ – Claies