I would like to be able to edit and display complex model in a <textarea>
element. Here's the HTML piece for generating model's fields dynamically from JSON response:
<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>
The output is the following:
But if I try to add a ngModel
to a textarea element to be able to edit this values in place like this:
<div class="preview">
<p>Preview: </p>
<textarea ng-model="createChildResource" style="height:350px; width:550px; overflow:scroll;">{{createChildResource | json}}</textarea>
</div>
then the output is the following:
In both cases I can't edit my model in a textarea element.
How can this be achieved? I'd like to be able to display and edit my model inplace like in this example with a slight difference: editable-textarea="user.description"
should be editable-textarea="user"
.
I finally understand what you are trying to achieve. On the left you have a bunch of inputs and on the right (bottom), you have a textarea that arranges the inputs as properties of one object and displays them formatted as an object.
Your requirements is to allow user to edit the property values in the textarea and thus update the corresponding property value in the input.
First, as commented, convert the object to a string and then show it inside the textarea.
Next, since you need to react and update the input fields when the textarea is updated, you need to watch
the value of the textarea and update the original object (the one that was converted to string).
Using an example here since your code is too complex to understand, let us say that you have the object containerObject
as follows:
$scope.containerObject = {
property_1: "Hello",
property_2: "World"
};
Your inputs then make use of these properties:
<input ng-model="containerObject.property_1">
<input ng-model="containerObject.property_2">
Now, you wish to display this inside your textarea - you will first convert the object to string and display it as follows:
$scope.getObjectAsText = function () {
$scope.textAreaModel = JSON.stringify($scope.containerObject);
};
And your textarea markup will look like:
<textarea ng-model="textAreaModel"></textarea>
Each time the value in the input textboxes change, the textarea also gets updated.
Now, for the other way around. When you change the textarea, to have the input textboxes get updated, you need to watch the string model (and NOT the object model):
$scope.$watch('textAreaModel', function () {
try {
$scope.containerObject = JSON.parse($scope.textAreaModel);
} catch(exp) {
//Exception handler
};
});
You need to have the try...catch
exception handler block because the user may accidentally change the contents such that on converting back to object, the result is not a suitable object (invalid property or invalid syntax).
As long as only the property value is changed, the input values will get updated correctly.
You can also wrap it into directive like below, or check the 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);
})
}
}
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With