Asp.net mvc AngularJS:如何从任意类型获取属性?
我这里有一个复杂的要求,一个真正令人头痛的人。。。我不确定最好的方法是什么: 要求: 根据管理UI的其余部分,在前端使用AngularJS构建一个页面,用于管理MVC5中的widgets CMS内容块。问题是每个小部件都有自己的一组特定属性。它们都有一些共同的属性,如标题、可访问性等。。但是一个HTML小部件将有一个BodyContent字段,一个Slider小部件将有一个图像集合,等等 我的第一个想法是使用[UIHint]和Html.EditorFor,这样每个小部件类型都有自己的标记。。我认为这很简单,但是我们如何将任意小部件的属性输入AngularJS模型呢 示例控制器 这可能吗?有更好的解决办法吗?注意,如果可以支持我的需求,我可以考虑更改代码以使用KokOutt或其他这样的框架。 编辑 请注意,这个问题更加复杂,因为需要将这样的模型传递回服务器并在那里进行处理。在常规MVC控制器中,我可以使用Request.Form来检查还有哪些其他值,但我使用的是WebAPI,不确定是否有可能 编辑2 好吧,我想我的思路是对的,但还是有问题。首先,我的进展如下: 我发现了关于.factory的信息,并制作了如下测试页面:Asp.net mvc AngularJS:如何从任意类型获取属性?,asp.net-mvc,angularjs,asp.net-web-api,asp.net-mvc-5,Asp.net Mvc,Angularjs,Asp.net Web Api,Asp.net Mvc 5,我这里有一个复杂的要求,一个真正令人头痛的人。。。我不确定最好的方法是什么: 要求: 根据管理UI的其余部分,在前端使用AngularJS构建一个页面,用于管理MVC5中的widgets CMS内容块。问题是每个小部件都有自己的一组特定属性。它们都有一些共同的属性,如标题、可访问性等。。但是一个HTML小部件将有一个BodyContent字段,一个Slider小部件将有一个图像集合,等等 我的第一个想法是使用[UIHint]和Html.EditorFor,这样每个小部件类型都有自己的标记。。我认
<div ng-app="myApp">
<div ng-controller="controller1">
<button class="btn btn-primary" ng-click="showAllInfo()">Show Info</button>
</div>
<div ng-controller="controller2">
</div>
</div>
<script type="text/javascript">
var myApp = angular.module('myApp', []);
myApp.factory('widgetModel', function () {
return {
id: '00000000-0000-0000-0000-000000000000',
title: '',
order: 0,
enabled: false,
widgetName: '',
widgetType: '',
zoneId: '00000000-0000-0000-0000-000000000000',
displayCondition: '',
widgetValues: '',
pageId: null,
cultureCode: '',
refId: null,
};
});
// This is representative of the main controller
myApp.controller('controller1', function ($scope, widgetModel) {
$scope.emptyGuid = '00000000-0000-0000-0000-000000000000';
$scope.model = widgetModel;
$scope.model.id = $scope.emptyGuid;
$scope.showAllInfo = function () {
alert("id: " + $scope.model.id + ", New Property: " + $scope.model.myNewProperty);
};
});
// This is representative of the details controller (to add properties specific to that particular widget type)
myApp.controller('controller2', function ($scope, widgetModel) {
$scope.model = widgetModel;
$scope.model.myNewProperty = "My Awesome Widget";
});
</script>
行得通。。我可以在那里看到我的新属性的html控件。。以下代码段是注入上述div的HTML:
当我点击测试按钮时,什么也没发生
我尝试通过此链接中概述的方法动态加载控制器:
它不起作用。不过老实说,我对AngularJS是个新手,并不真正了解它的所有细节。。任何帮助都会很好。如果您只是想获取属性及其值,那么在AngularJS或Javascript端,您可以迭代对象属性,以获取对象上定义的所有属性
for(var key in obj){
$scope[key]=obj[key];
}
一旦进入范围,您就可以使用ng模型将其绑定到视图。
这种方法可以获得数据,但有关数据的元数据(如要为属性需求呈现的控件)不起作用
对于高级方案,您应该尝试发送有关每个属性的元数据,以帮助在视图上呈现这些属性
如果ng模型设置正确,所有数据都将发送到服务器
在服务器上,您可以使用dynamic关键字作为webapi方法的输入参数,并且应该有类似的方法使用键值对迭代有效负载。我最终改为KnockoutJS,部分原因是AngularJS对我的需求来说有点过分,但也因为它不能很好地处理这种情况,或者至少没有明显和干净的方法来处理。我的KnockoutJS解决方案如下: 在主页面中,我添加了一个html元素: 要注入的任意HTML示例:
<div id="widget-content" class="col-sm-12 col-md-12">
<div class="form-group">
@Html.Label("BodyContent", "Body Content", new { @class = "control-label" })
@Html.TextArea("BodyContent", null, new { @class = "form-control", data_bind = "wysiwyg: bodyContent, wysiwygConfig: tinyMCEConfig" })
</div>
</div>
<script type="text/javascript">
function updateModel() {
var data = ko.mapping.fromJSON(viewModel.widgetValues());
viewModel.bodyContent = ko.observable("");
if (data && data.BodyContent) {
viewModel.bodyContent(data.BodyContent());
}
viewModel.tinyMCEConfig = {
theme: "modern",
plugins: [
"advlist autolink lists link image charmap print preview hr anchor pagebreak",
"searchreplace wordcount visualblocks visualchars code fullscreen",
"insertdatetime media nonbreaking save table contextmenu directionality",
"emoticons template paste textcolor"
],
toolbar1: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image",
toolbar2: "print preview media | forecolor backcolor emoticons",
image_advtab: true,
templates: [
{ title: 'Test template 1', content: 'Test 1' },
{ title: 'Test template 2', content: 'Test 2' }
],
content_css: tinyMCEContentCss
};
};
function onBeforeSave() {
var data = {
BodyContent: viewModel.bodyContent()
};
viewModel.widgetValues(ko.mapping.toJSON(data));
};
</script>
非常有效。谢谢你的回复,但我发现我认为这是一种更干净的方法。然而,我仍然有问题。请看我上面的编辑。很多编辑。。。分为两个问题,您可能会得到更好的答案。html仍然包含服务器端标记。这是行不通的。
<div ng-controller="widgetDetailsController">
<div class="col-sm-12 col-md-12">
<div class="form-group">
@Html.Label("BodyContent", "Body Content", new { @class = "control-label" })
@Html.TextArea("BodyContent", null, new { @class = "form-control", ng_model = "model.bodyContent", ui_tinymce = "tinyMCEOptions_BodyContent" })
</div>
</div>
<button class="btn" ng-click="test()">Test</button>
</div>
<script type="text/javascript">
widgetsApp.controller('widgetDetailsController', function ($scope, $http, widgetModel) {
$scope.model = widgetModel;
$scope.json = angular.fromJson($scope.model.widgetValues);
$scope.model.bodyContent = $scope.json.bodyContent || "";
$scope.test = function () {
alert($scope.model.bodyContent);
};
});
</script>
for(var key in obj){
$scope[key]=obj[key];
}
<div id="widget-content" class="col-sm-12 col-md-12">
<div class="form-group">
@Html.Label("BodyContent", "Body Content", new { @class = "control-label" })
@Html.TextArea("BodyContent", null, new { @class = "form-control", data_bind = "wysiwyg: bodyContent, wysiwygConfig: tinyMCEConfig" })
</div>
</div>
<script type="text/javascript">
function updateModel() {
var data = ko.mapping.fromJSON(viewModel.widgetValues());
viewModel.bodyContent = ko.observable("");
if (data && data.BodyContent) {
viewModel.bodyContent(data.BodyContent());
}
viewModel.tinyMCEConfig = {
theme: "modern",
plugins: [
"advlist autolink lists link image charmap print preview hr anchor pagebreak",
"searchreplace wordcount visualblocks visualchars code fullscreen",
"insertdatetime media nonbreaking save table contextmenu directionality",
"emoticons template paste textcolor"
],
toolbar1: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image",
toolbar2: "print preview media | forecolor backcolor emoticons",
image_advtab: true,
templates: [
{ title: 'Test template 1', content: 'Test 1' },
{ title: 'Test template 2', content: 'Test 2' }
],
content_css: tinyMCEContentCss
};
};
function onBeforeSave() {
var data = {
BodyContent: viewModel.bodyContent()
};
viewModel.widgetValues(ko.mapping.toJSON(data));
};
</script>
$.ajax({
url: "/admin/widgets/get-editor-ui/" + self.id(),
type: "GET",
dataType: "json",
async: false
})
.done(function (json) {
var result = $(json.Content);
var content = $(result.filter('#widget-content')[0]);
var details = $('<div>').append(content.clone()).html();
$("#widget-details").html(details);
var scripts = result.filter('script');
scripts.appendTo('body');
// ensure the function exists before calling it...
if (typeof updateModel == 'function') {
updateModel();
var elementToBind = $("#widget-details")[0];
ko.cleanNode(elementToBind);
ko.applyBindings(viewModel, elementToBind);
}
})
.fail(function () {
$.notify("There was an error when retrieving the record.", "error");
});
// ensure the function exists before calling it...
if (typeof onBeforeSave == 'function') {
onBeforeSave();
}