AngularJS: привязка textarea к объекту JSON показывает "объект-объект"
Я новичок в AngularJS.
Я пытаюсь связать объект с текстовым полем.
HTML:
<textarea rows="5" cols="10" ng-model="menuItem.preset"></textarea>
Модель:
{
"kind": "title",
"label": "ADD_TITLE",
"iconSrc": "textTitle.png",
"experimentInclude": "",
"experimentExclude": "three",
"preset": {
"compType": "richTitle",
"styleId": "txtNew"
}
}
Результат:
![json shown as object]()
Как я могу показать сжатый JSON (и позже сохранить его как объект снова)?
Ответы
Ответ 1
Вам нужна настраиваемая директива, которая анализирует входные данные для объекта и отображает объект как строку, соответственно:
Что-то вроде:
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);
}
};
});
<textarea json-text rows="5" cols="10" ng-model="menuItem.preset"></textarea>
Fiddle: http://jsfiddle.net/HzYQn/
Ответ 2
Я только что исследовал то, что, по моему мнению, самый "правильный" способ сделать это, поскольку мне это нужно для моего https://github.com/vorburger/MUI.js... Итак вот Plonker с моим решением. Его основанный на и, по сути, особый случай (например, приложение) связанного Q Как сделать двустороннюю фильтрацию в angular.js? Добавленный поворот обновления модели также должны изменить текстовое поле.. то, что делает вещь $watch/$setViewValue/$render.
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"
}
};
}
]);
<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>
Ответ 3
попробуйте с json-фильтром
<textarea rows="5" cols="10" >
{{ menuItem.preset | json }}
</textarea>
Ответ 4
Вот наша директива 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 "";
}
});
}
};
});
Когда пользователь вводит недопустимый JSON, модель имеет значение null. Когда модель содержит циклические ссылки или имеет значение NULL, пользователь увидит пустую строку (""), и вход недействителен.
Enjoy.
Ответ 5
также вы можете определить метод toString на вашей модели:
$scope.menuItem.preset.toString = function(){
return JSON.stringify(this);
}
http://jsfiddle.net/ceJ4w/19/
а затем синхронизировать часы с обратным использованием
http://jsfiddle.net/ceJ4w/20/
но он больше похож на грязный хак, чем на решение
Ответ 6
Вы можете сделать это в два этапа:
Ответ 7
Является ли использование события ng-change слишком грязным?
<textarea ng-model="textmainboardJSON" ng-change="updateMainboard()"
http://jsfiddle.net/gsw9Q/3/
Ответ 8
Попробуйте это. Он работал в моем случае
<textarea rows="5" cols="10" >{{menuItem.preset}}</textarea>
Ответ 9
У меня есть простой способ привязать данные массивов к текстовой области в angularjs. Когда есть два массива и вам нужно показать их параллельно. Далее вы можете получить его и на jsfiddle.
http://jsfiddle.net/Ahsan_Aftab/bc7hd258/18/
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js">
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<textarea ng-model="TextAreacodeGroups" style="width:52%;height:200px;" columns="25" id="code_groups">
{{CodeGroupsFun()}}
</textarea>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
var combined;
var array1=['01','02','03','04'];
var array2= ['Students','Teachers','Managers','Operators'];
$scope.CodeGroupsFun = function () {
$scope.TextAreacodeGroups =
combined = array1.map(function (e, i) {
return '\n' + array1[i] + ' - ' + array2[i];
});
};
});
</script>
</body>
</html>