我希望能够在<textarea>
元素中编辑和显示复杂模型。这是用于从JSON响应动态生成模型字段的HTML部分:
<p>parent uuid*: </p>
<input ng-model="parentUuid" capitalize type="text" placeholder="String"
class="form-control" style="width:200px; display: inline-block;"/> <br/>
<p>resource*:</p>
<select ng-model="childResource" ng-change="loadResourceFields(childResource)"
class="form-control" style="width:300px; display: inline-block;">
<option ng-repeat="childResource in restResources">{{childResource}}</option>
</select>
<div ng-repeat="field in childFields">
<div ng-show={{!field.isEnum}}>
<p ng-show={{field.isRequired}}>{{field.name}}*: </p>
<p ng-show={{!field.isRequired}}>{{field.name}}: </p>
<input type="text" ng-model="createChildResource[field.name]"
class="form-control" style="width:200px; display: inline-block;" placeholder="{{parseClassName(field.type)}}">
</div>
<div ng-show={{field.isEnum}}>
<p ng-show={{field.isRequired}}>{{field.name}}*: </p>
<p ng-show={{!field.isRequired}}>{{field.name}}: </p>
<select ng-model="createChildResource[field.name]" class="form-control" style="width:auto; display: inline-block;">
<option></option>
<option ng-repeat="enumValue in field.enumValues" label={{enumValue.name}}>{{enumValue.ordinal}}</option>
</select>
</div>
</div>
<div class="preview">
<p>Preview: </p>
<textarea style="height:350px; width:550px; overflow:scroll;">{{createChildResource | json}}</textarea >
</div>
输出如下:
但是,如果我尝试将ngModel
添加到textarea元素,以便能够像这样编辑这些值:
<div class="preview">
<p>Preview: </p>
<textarea ng-model="createChildResource" style="height:350px; width:550px; overflow:scroll;">{{createChildResource | json}}</textarea>
</div>
然后输出如下:
在这两种情况下,我都无法在textarea元素中编辑我的模型。
如何实现这一目标?我希望能够像this example一样在地方显示和编辑我的模型,但略有不同:editable-textarea="user.description"
应为editable-textarea="user"
。
答案 0 :(得分:10)
我终于明白你想要实现的目标。在左侧有一堆输入,在右侧(底部),您有一个textarea,它将输入排列为一个对象的属性,并将它们显示为对象。
您的要求是允许用户编辑textarea中的属性值,从而更新输入中的相应属性值。
首先,如评论所述,将对象转换为字符串,然后在textarea中显示它。
接下来,由于在更新textarea时需要对输入字段做出反应和更新,因此需要watch
textarea的值并更新原始对象(转换为字符串的对象)。 / p>
在此处使用示例,因为您的代码太复杂而无法理解,请假设您拥有对象containerObject
,如下所示:
$scope.containerObject = {
property_1: "Hello",
property_2: "World"
};
您的输入会使用这些属性:
<input ng-model="containerObject.property_1">
<input ng-model="containerObject.property_2">
现在,您希望在textarea中显示此内容 - 您将首先将对象转换为字符串并按如下方式显示:
$scope.getObjectAsText = function () {
$scope.textAreaModel = JSON.stringify($scope.containerObject);
};
您的textarea标记将如下所示:
<textarea ng-model="textAreaModel"></textarea>
每次输入文本框中的值发生变化时,textarea也会更新。
现在,反过来说。当您更改textarea时,要更新输入文本框,您需要观察字符串模型(而不是对象模型):
$scope.$watch('textAreaModel', function () {
try {
$scope.containerObject = JSON.parse($scope.textAreaModel);
} catch(exp) {
//Exception handler
};
});
您需要拥有try...catch
异常处理程序块,因为用户可能会意外更改内容,以便在转换回对象时,结果不是合适的对象(无效属性或语法无效)。
只要更改属性值,输入值就会正确更新。
答案 1 :(得分:4)
您也可以将其包装到下面的指令中,或查看jsfiddler
<强> HTML 强>
<div ng-app="app" ng-controller='userCtrl' >
<textarea obj-edit obj="user" rows='10'></textarea>
<p ng-bind='user.name'></p>
</div>
<强>的javascript 强>
var app = angular.module("app", []);
app.controller('userCtrl', function($scope) {
$scope.user= {name: 'ron', ocupation: 'coder'};
});
app.directive('objEdit', function() {
return {
restrict: 'A',
scope: {
obj:'=obj'
},
link: function(scope, element, attrs) {
element.text(JSON.stringify(scope.obj, undefined, 2));
element.change(function(e) {
console.log(e.currentTarget.value);
scope.$apply(function() {
scope.obj = JSON.parse(e.currentTarget.value);
});
console.log(scope.obj);
})
}
}
})
答案 2 :(得分:3)
Ron's answer很棒。
以下是使用ngModel
验证
<强> HTML 强>
<form name="text">
<textarea obj-edit ng-model="ctrl.json" name="json" rows="25" ng-model-options="{ debounce: 300 }"></textarea>
<div class="alert alert-danger" role="alert" ng-show="text.json.$error.json">
Error input
</div>
</form>
<强>的Javascript 强>
app.directive('objEdit', function() {
return {
restrict: 'A',
require: "ngModel",
link: function(scope, element, attrs, ctrl) {
ctrl.$formatters.push(function formatter(value) {
return JSON.stringify(value, undefined, 2);
});
ctrl.$parsers.push(function(value) {
try {
var result = JSON.parse(value);
ctrl.$setValidity('json', true);
return result;
} catch (e) {
ctrl.$setValidity('json', false);
return undefined;
}
});
}
}});