【问题标题】:Angular JS display and edit model in textareaAngular JS在textarea中显示和编辑模型
【发布时间】:2014-05-12 01:44:35
【问题描述】:

我希望能够在<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"

【问题讨论】:

  • createChildResource 是一个对象,因此在文本区域内显示为一个对象。尝试将对象转换为字符串 - 也许是JSON.stringify(),您应该会看到内容。
  • 我会试一试,如果有帮助,请告诉您。谢谢
  • 是的,现在我可以看到一个对象的内容,但我仍然无法更改它。
  • 您的意思是更改没有反映在控制器或视图的其他区域中,或者文本区域被禁用并且您无法编辑内容?
  • 视图没问题,但如果我尝试更改 textarea 内的任何内容 - 对象字段就不会更新。

标签: javascript json angularjs object


【解决方案1】:

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;
            }
        });

    }
}});

【讨论】:

    【解决方案2】:

    您也可以将其包装成如下指令,或查看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);
                })
            }
        }
    })
    

    【讨论】:

    • 是的,很好的解决方案:)
    • 不错的罗恩。我继续前进并通过在标准 ngModel codepen 中使用 $parsers$formatters 采取了额外的步骤。
    【解决方案3】:

    我终于明白你想要达到的目的了。在左侧有一堆输入,在右侧(底部)有一个 textarea,它将输入排列为一个对象的属性,并将它们显示为一个对象。

    您的要求是允许用户编辑文本区域中的属性值,从而更新输入中的相应属性值。

    首先,如注释,将对象转换为字符串,然后将其显示在文本区域内。

    接下来,由于更新文本区域时需要对输入字段做出反应并更新,因此需要watch文本区域的值并更新原始对象(转换为字符串的对象)。

    由于您的代码太复杂而无法理解,因此在这里使用示例,假设您有对象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>
    

    每次输入文本框中的值发生变化时,文本区域也会更新。

    现在,反过来。当您更改文本区域时,要更新输入文本框,您需要查看字符串模型(而不是对象模型):

    $scope.$watch('textAreaModel', function () {
        try {
            $scope.containerObject = JSON.parse($scope.textAreaModel);
        } catch(exp) {
            //Exception handler
        };
    });
    

    您需要有try...catch 异常处理程序块,因为用户可能会意外更改内容,以便在转换回对象时,结果不是合适的对象(无效属性或无效语法)。

    只要只更改属性值,输入值就会正确更新。

    【讨论】:

    • 是的,您正确理解了目标和要求。在我看来,这个解决方案可以正常工作。无论如何,感谢您的巨大贡献。它清除了一些问题。你的答案是 100% 有用的。一旦我得到一些结果,我会通知你。谢谢 :)
    • 我应该在哪里使用函数 getObjectAsText()?
    • 我猜它应该是每个输入的 ng-change="getObjectAsText()" ?
    • 太好了,它帮助了我 :) 但是还有一个问题:textarea 中的字符串与之前的字符串相比格式很难看。任何想法如何处理?如果您也可以帮助我,我将创建一个单独的问题。这个问题就解决了。非常感谢:)
    • 我的错 - 我最初打算使用 getObjectAsText() 作为视图中的模型,但后来我改变主意改用 textAreaAsModel。您可以在ng-change 指令中使用它,也可以这次在对象上设置另一个$scope.$watch(),并在每次输入更改时调用getObjectAsText() 来更新textarea 内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多