【问题标题】:Dynamically generate ng-model in AngularJS在 AngularJS 中动态生成 ng-model
【发布时间】:2014-12-18 23:55:49
【问题描述】:

我正在尝试使用过滤器动态生成 ng-model 指令。 主要思想是数据库中有一些文本。此文本有由方括号([1]、[2] 等)之间的数字定义的空白。目的是解析这些差距并将它们转化为输入。然后应该使用 ng-model 指令将这些输入绑定到一个变量,但我无法让它工作。

这是我的控制器

 app.controller('exerciseTemplateCtrl', ['$http', '$scope', '$sce', '$filter', '$compile',  function($http, $scope, $sce, $filter, $compile){

    // used to test the binding through ng-model
    $scope.answers = [];

    $http.get('encode_exercises.json')
         .then(function(response){
            $scope.firstExercise = response.data;
        });

    $scope.parseHtml = function(input){
        input = $filter('gapToInput')(input);
        return $sce.trustAsHtml(input);
    };

}]);

这是我的过滤器“gapToInput”

app.filter('gapToInput', function(){
    return function(input){
        return input.replace(/\[[0-9]\]/g, '<input type="text" ng-model="answers">');
    };
});

如您所见,我正在使用“answers”变量绑定模型。 这是我的指令

app.directive('exerciseTemplate', function(){
  return{
    restrict: 'E',
    templateUrl: 'exercise-template.html'
  };
});

index.html 包含前面的指令:

<exercise-template></exercise-template>

这里是我的上一个指令的模板(简化)

<div ng-controller="exerciseTemplateCtrl as e">
    <div ng-repeat="exercise in firstExercise">
        <div ng-repeat="(questionId, question) in exercise.q">
            <div ng-bind-html="parseHtml(question.d.q)"></div>
        </div>
    </div>
    <p><button>Check</button></p>
</div>

question.d.q 包含来自数据库的带有空白的文本([1]、[2] 等),它正在成功应用过滤器(抱歉,我没有足够的声誉来发布图片):

http://i.stack.imgur.com/W0NoI.png

问题在于,即使替换有效,ng-model 指令也不会将每个输入与“answers”变量绑定。 对于我一直在阅读的内容,这是因为我必须再次重新编译模板,以便 Angular 再次解析所有 ng 指令。尝试做以下没有任何运气:

var scope = $scope;
$scope.parseHtml = function(input){
    input = $filter('gapToInput')(input);
    input = $compile(input)(scope);
    return $sce.trustAsHtml(input);
};

我也关注了this thread,并尝试将指令格式更改为以下内容:

app.directive('exerciseTemplate', ['$compile', '$http', function($compile, $http){
    return {
        restrict: 'E',
        link: function(scope, element, attrs){
            $http.get('exercise-template.html').then(function(result){
                element.replaceWith($compile(result.data)(scope));
            });
        }
    }
}]);

但它仍然没有绑定模型。即使是最简单的事情,我也开始对 Angular 的困难程度感到有点沮丧,所以任何帮助都将不胜感激。

谢谢

【问题讨论】:

    标签: javascript html angularjs


    【解决方案1】:

    我还没有测试过这段代码,但这里的重点是您可以使用 ng-repeat 上的内联过滤器来拆分“间隙”。这将返回一个项目数组,您可以以此为基础建立模型。

    <div ng-repeat="exercise in firstExercise">
        <div ng-repeat="(questionId, question) in exercise.q | gapToInput">
            <input ng-repeat="" type="text" ng-model="exercise.q[questionId].answer">
        </div>
    </div>
    

    你的过滤器在哪里:

    app.filter('gapToInput', function(){
        return function(input){
            return input.split(/\[[0-9]\]/g);
        };
    });
    

    【讨论】:

    • 感谢您的评论。那可以工作。会试一试并发布结果。
    • 好吧,我刚刚测试了它,它可以工作!我现在必须解决一些布局问题,因为其中一些输入可以在表格单元格内,并且添加输入会破坏表格格式,但也许我可以找到解决方案。非常感谢!
    【解决方案2】:

    经过一番调查,我设法找到了解决我最初问题的方法。即使SoluableNonagon 回答的工作,我将发布另一种方式来处理我的问题。

    这个想法与我第二次重新编译模板的尝试非常相似,但我可能遗漏了一些东西,所以这里是完整的工作代码:

    指令

    app.directive('exerciseTemplate', function(){
        return{
            restrict: 'E',
            scope: true,
            templateUrl: '/exercise-template.html'
        };
    });
    
    app.directive('qText', ['$compile', '$timeout', function($compile, $timeout){
        return {
            restrict: 'E',
            link: function(scope, element, attrs){
                $timeout(function(){
                    var output = element.html().replace(/\[[0-9]\]/g, '<input type="text" ng-model="answers">');
                    element.html(output);
                    $compile(element.contents())(scope);
                });
            }
        }
    }]);
    

    exercise-template.html

    <q-text ng-bind-html="parseHtml(question.d.q)"></q-text>
    

    这将获取的内部HTML并将其传递给指令的链接函数。然后我使用 jQLite 的 html() 函数来检索 HTML 并用输入替换每个间隙,之后我只需将 HTML 放回元素中并重新编译模板。之后,每个输入都将通过 ng-model 指令与“answers”变量绑定。

    我不得不使用 $timeout,否则 html() 方法返回 null,可能是因为 DOM 还没有准备好。不知道这是否是一个好的做法,但这是我能找到的唯一方法。

    任何建议或建议将不胜感激。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多