javascript - AngularJS 中的动态表单

标签 javascript angularjs angularjs-scope

我正在为客户开发一个 CMS,它全部基于 AngularJS 及其 Controller 、 View 、服务等。

我需要的是一种模式,其中动态加载的脚本在现有范围内注入(inject)一些数据

好吧,用人类的话来说:我有一个由 Controller 管理的表单。该表单有几个预设字段。这些字段由范围数组管理,例如:

$scope.fields = [
  { type: "text", name="first_name" },
  { type: "text", name="last_name" },
  { type: "email", name="email" }
];

View 动态打印字段(即它是一个脚手架)。

当客户登录到应用程序时,我检查他的个人资料中是否有要加载的自定义脚本,如果有,应用程序会将 javascript 附加到 DOM,javascript 文件名等于登录用户的用户名。

因此,如果用户名为“darko”并且他启用了自定义脚本,则应用程序会将此文件附加到 DOM:

/js/customers/darko.js

假设 darko 在表单内还有更多字段要显示(和保存),我该怎么做?我需要挂接 Controller ,以便可以访问其范围,然后注入(inject)我的字段。像这样的东西:

var $scope = getUserFormScope();//some magic....
$scope.fields.push({ type: "text", name="skype" });

但是,具有更多字段的表单只是一个示例,更一般地说,我真正需要的是一种“ Hook Controller ”并访问其范围的方法。

有什么想法吗?

解决方案

我终于使用了marfarma建议的方法。自定义脚本包含一个或多个部分 Controller ,其名称与它们想要扩展的 Controller 的名称相同,前缀为 Custom 单词,然后我用这些部分 Controller 扩展我的 Controller 。例如,我的应用程序有一个名为 PageController 的 Controller ,在该 Controller 内我检查 CustomPageController 是否存在:

if (typeof CustomPageController == 'function') {
    angular.extend(this, CustomPageController($scope));
}

如果是这样,我用自定义 Controller 扩展主 Controller 。

最佳答案

这是“ Hook Controller ”并访问其作用域的通用方法 - 通过 angular.extend 混合 Hook 代码。

function CustomUserController($scope) {
    // contents of this hook controller is up to you

    var _this = this;

    // Mixin instance properties.
    this.vocalization = getValue('vocalization',$scope.user);
    this.runSpeed = getValue('runSpeed'        ,$scope.user);

    // Mixin instance methods.
    this.vocalize = function () {
        console.log(this.vocalization);
    };

    // Mixin scope properties.
    $scope.color = color;

    // Mixin scope methods.
    $scope.run = function(){
        console.log("run speed: " + _this.runSpeed );
    };
}

function PageController($scope) {

    var _this = this;
    $scope.user; // this should be the current user obj, with key for custom script lookup

    // Mixin Custom Script into Controller.
    if (userService.hasCustomScript($scope.user)) {
        angular.extend(this, new CustomUserController($scope));
    }
}

对于您的具体示例,将任意字段插入表单的一种方法是动态构建它。我使用可能适合您情况的模式表单指令。给定一个定义模型属性的模式和一个指定项目包含顺序的数组,该指令会布置表单。

例如(另请参阅此 working plunker, incl. add'l features ):

<form class="form-inline" name="form" novalidate role="form">
    <div class="row-fluid clearfix">
        <h2>Sample Form</h2>
    </div>
    <div class="row-fluid clearfix">
        <hr> 
        <div class="span12">
            <fieldset class="span6">
                <schema-form-fields
                    fields="side1Fields"
                    model="model"
                    schema="modelSchema"
                    data="requestResult"
                    schema-list="schema">
                </schema-form-fields>
            </fieldset>
            <fieldset class="span6">
                <schema-form-fields
                    fields="side2Fields"
                    model="model"
                    schema="modelSchema"
                    data="requestResult"
                    schema-list="schema">
                </schema-form-fields>
            </fieldset>
        </div>
    </div>
    <div class="row-fluid clearfix">
        <button
            class="btn btn-primary span2 offset10"
            type="submit">
            Submit
        </button>
    </div>
</form>
// example controller with dynamic form
app.controller('HomeCtrl', ['$scope', 'schema', 'requestResult', 'dataService',
    function($scope, schema, requestResult, dataService) {

        $scope.modelSchema = schema.product;          
        $scope.model = {
            factoryDate: '20160506'
        };

        // field name arrays - one array per column in sample layout
        // insert elements into these and form should re-render
        // may require explicit watch to trigger update
        $scope.side1Fields = [
            'productName',
            'factoryDate'
        ];

        $scope.side2Fields = [
            'productType',
            'timeValue'
        ];  

        // ....  other controller code    
    }
]);
// example schema
app.value('schema', {
    "product": {
        "type": "object",
        "title": "Product Schema",
        "properties": {
            "productType": {
                "type": "string",
                "title": "Product Type",
                "showLabel": true,
                "tooltip": "Product classification",
                "readonly": false,
                "required": true,
                "class": "custom-select",
                "enum": ['Bike', 'Car', 'Airplane', 'Glider', 'Stilts']
            },
            "productName": {
                "title": "Product Name",
                "showLabel": true,
                "type": "string",
                "tooltip": "A more descriptive name for the modeled structure.",
                "readonly": false,
                "required": true
            },
            "factoryDate": {
                "title": "Factory Date",
                "type": "string",
                "showLabel": true,
                "control": "date",
                "dateFormat": "yyyymmdd",  // TODO format as provided 
                "tooltip": "Date of manufacture.",
                "dateOptions": {
                    autoclose: true
                },
                "readonly": false,
                "required": true
            },
            "timeValue": {
                "title": "Time (HHMM)",
                "showLabel": true,
                "type": "string",
                "pattern": "([0-1]{1}[0-9]{1}|20|21|22|23)[0-5]{1}[0-9]{1}",
                "timeFormat": "hhmm",  // TODO format as provided 
                "tooltip": "Time entry.",
                "readonly": false,
                "required": true,
            }
        }
    }
});

关于javascript - AngularJS 中的动态表单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24741092/

相关文章:

javascript - for循环中的setTimeout()的clearTimeout()

javascript - Angularjs 从一个 Controller 继承另一个 Controller 的属性

javascript - 为什么绑定(bind)在 Angular js 中不起作用?

javascript - 测试 mongo 脚本中参数是否存在

javascript - 异步 .eachLimit 回调错误未调用

javascript - 如何使用 jquery 或 javascript 编写检查验证的条件

javascript - 输入框中的 Angularjs 货币格式与 ng-model : how to get $formatters to fire on each input

javascript - 如何使用 AngularJS 设置 select 的默认选项?

javascript - Protractor 多尺寸浏览器

javascript - 在 AngularJS 中,我的指令无法访问 $http 中定义的父 Controller 的 $scope 属性