AngularJS:textarea绑定到JSON对象显示"object-object"

Guy*_*Guy 40 angularjs

我是AngularJS的新手.

我试图将对象绑定到textarea.

HTML:

<textarea rows="5" cols="10" ng-model="menuItem.preset"></textarea>
Run Code Online (Sandbox Code Playgroud)

模型:

{
    "kind": "title",
    "label": "ADD_TITLE",
    "iconSrc": "textTitle.png",
    "experimentInclude": "",
    "experimentExclude": "three",
    "preset": {
        "compType": "richTitle",
        "styleId": "txtNew"
    }
}
Run Code Online (Sandbox Code Playgroud)

结果:

json显示为对象

如何显示字符串化的JSON(以后再将其另存为对象)?

hol*_*ple 29

您需要一个自定义指令来解析对象的输入,并将对象分别显示为字符串:

就像是:

angular.module('yourApp').directive('jsonText', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attr, ngModel) {            
          function into(input) {
            return JSON.parse(input);
          }
          function out(data) {
            return JSON.stringify(data);
          }
          ngModel.$parsers.push(into);
          ngModel.$formatters.push(out);

        }
    };
});
Run Code Online (Sandbox Code Playgroud)
<textarea json-text rows="5" cols="10" ng-model="menuItem.preset"></textarea>
Run Code Online (Sandbox Code Playgroud)

小提琴:http://jsfiddle.net/HzYQn/

  • 对于漂亮的打印使用`return JSON.stringify(data,undefined,2);` (7认同)
  • 对于2路数据绑定,我必须添加`scope.$ watch(attr.ngModel,function(newValue){element [0] .value = out(newValue);},true);` (3认同)

vor*_*ger 25

我刚刚研究了我认为最合适的方式,因为我需要它来自我的https://github.com/vorburger/MUI.js ...所以这是一个Plonker与我的解决方案.它基于&本质上是一个特殊情况(即应用程序)相关Q 如何在angular.js中进行双向过滤?增加的扭曲是模型更新也应该改变文本框..这就是$ watch/$ setViewValue/$渲染事物的作用.

var app = angular.module('app', []);

app.directive('jsonText', function() {
  return {
    restrict: 'A', // only activate on element attribute
    require: 'ngModel', // get a hold of NgModelController
    link: function(scope, element, attrs, ngModelCtrl) {

      var lastValid;

      // push() if faster than unshift(), and avail. in IE8 and earlier (unshift isn't)
      ngModelCtrl.$parsers.push(fromUser);
      ngModelCtrl.$formatters.push(toUser);

      // clear any invalid changes on blur
      element.bind('blur', function() {
        element.val(toUser(scope.$eval(attrs.ngModel)));
      });

      // $watch(attrs.ngModel) wouldn't work if this directive created a new scope;
      // see https://stackoverflow.com/questions/14693052/watch-ngmodel-from-inside-directive-using-isolate-scope how to do it then
      scope.$watch(attrs.ngModel, function(newValue, oldValue) {
        lastValid = lastValid || newValue;

        if (newValue != oldValue) {
          ngModelCtrl.$setViewValue(toUser(newValue));

          // TODO avoid this causing the focus of the input to be lost..
          ngModelCtrl.$render();
        }
      }, true); // MUST use objectEquality (true) here, for some reason..

      function fromUser(text) {
        // Beware: trim() is not available in old browsers
        if (!text || text.trim() === '') {
          return {};
        } else {
          try {
            lastValid = angular.fromJson(text);
            ngModelCtrl.$setValidity('invalidJson', true);
          } catch (e) {
            ngModelCtrl.$setValidity('invalidJson', false);
          }
          return lastValid;
        }
      }

      function toUser(object) {
        // better than JSON.stringify(), because it formats + filters $$hashKey etc.
        return angular.toJson(object, true);
      }
    }
  };
});


app.controller('Ctrl', ['$scope',
  function($scope) {
    $scope.model = {};
    $scope.model.data = {
      "kind": "title",
      "label": "ADD_TITLE",
      "iconSrc": "textTitle.png",
      "experimentInclude": "",
      "experimentExclude": "three",
      "preset": {
        "compType": "richTitle",
        "styleId": "txtNew"
      }
    };
  }
]);
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<div ng-app="app" class="container">
  <div ng-controller="Ctrl" class="row">
    <textarea json-text ng-model='model.data' rows="15"></textarea>
    <p>{{ model.data }}</p>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)


小智 12

尝试用json过滤器

<textarea rows="5" cols="10" >
   {{ menuItem.preset | json }}
</textarea>
Run Code Online (Sandbox Code Playgroud)

  • 这不会将值绑定回范围 (10认同)

Vin*_*ent 5

这是我们的JSON指令,带有效性检查:

app.directive('jsonInput', function () {
  'use strict';
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function (scope, elem, attr, ctrl) {
        ctrl.$parsers.unshift(function(input) {
          try {
            var obj = JSON.parse(input);
            ctrl.$setValidity('jsonInput', true);
            return obj;
          } catch (e) {
            ctrl.$setValidity('jsonInput', false);
            return null;
          }
        });
        ctrl.$formatters.unshift(function(data) {
          if (data == null) {
            ctrl.$setValidity('jsonInput', false);
            return "";
          }
          try {
            var str = JSON.stringify(data);
            ctrl.$setValidity('jsonInput', true);
            return str;
          } catch (e) {
          ctrl.$setValidity('codeme', false);
              return "";
          }
        });
    }
  };

});
Run Code Online (Sandbox Code Playgroud)

当用户输入无效的JSON时,模型为空.当模型包含循环引用或为null时,用户将看到空字符串("")并且输入无效.

请享用.