Angular JS:使用filter / directive修改生成的输出

时间:2014-04-12 10:22:31

标签: javascript angularjs

在我的应用程序中,我有不同的任务,每个任务的截止日期可能如下:

Jun 6, 2014
Apr 12, 2014 @ 1pm
Daily @ 1pm

在我看来,我使用ng-repeat来显示任务及其相关信息。我的ng-repeat如下所示:

  <ul class="tasks">
   <li class="single-task">
       <span class="task-title">{{task.title}}</span>
       <span class="task-duedate">{{task.dueDate}}</span>
   </li>

我想要的是以不同方式显示日期,而不是以存储方式显示日期,我希望日期在<span class="task-duedate"></span>内呈现,如下所示:

<span class="task-duedate">
    <span class="date-daymon">Apr 12</span>
    <span class="date-year">2014</span>
    <span class="date-time">1 pm</span>
</span>

所以,我创建并应用了一个名为filter

NormalizeDateTime
<span class="task-duedate">{{task.dueDate | NormalizeDateTime }}</span>

生成所需的html并返回它。

app.filter('NormalizeDate', function(){
return function( input ) {
        ...
        ...
        return '<span..>' + date + '</span><span..>' + year + '</span><span..>' + time + '</span>';
    };
});

现在我遇到的问题是角度,而不是让浏览器呈现返回的html,而是显示过滤器返回的日期部分,即纯文本形式。现在问题是,如何将NormalizeDateTime过滤器返回的文本呈现为html?

P.S我也尝试过三重括号{{{task.dueDate | NormalizeDateTime}}},就像我们在HandlebarsJS中所做的那样,但这也不起作用。

更新 我试图使用自定义指令实现相同的目标:

<span class="task-content group cursor-text group left">
    <span class="task-text cursor-text">{{task.title}}</span>
    <span class="task-trackedtime right">{{task.trackedTime}}</span>
    <span class="task-datetime right" duedate="{{task.dueDate}}"></span>
</span>

以下是我的指令的样子:

app.directive('duedate', [function () {
    return {
        restrict: 'A',
        // transclude: true,
        replace: true,
        template: '<span class="task-datetime right">{{dat}}</span>',
        link: function (scope, iElement, iAttrs) {
            // scope.dat = 'Testing Date';
            console.log(iAttrs.duedate);
        }
    };
}])

但我无法在我的指令的iAttrs内访问duedatelink。为什么会这样?

5 个答案:

答案 0 :(得分:2)

我也遇到了过滤器无法生成HTML并恢复到指令的问题。

我建议您对指令进行一些小改动,即添加范围定义,如下所示:

app.directive('duedate', [function () {
    return {
        restrict: 'A',
        replace: true,
        scope: {
            dat: '@duedate'
        },
        template: '<span class="task-datetime right">{{dat}}</span>',
        link: function (scope, iElement, iAttrs) {
            // scope.dat = 'Testing Date';
            console.log(scope.dat);
        }
    };
}])

通过添加scope: { dat: '@duedate' },您可以指定指令的范围dat属性应设置为duedate属性的解释值。

答案 1 :(得分:1)

不确定但是在你的范围

中使用ngBindHtml指令的行中尝试了一些东西

<span class="task-duedate" ng-bind-html='task.dueDate | NormalizeDateTime'></span>

看看它是否有效。请记住包含ngSanitize模块。

请参阅文档http://docs.angularjs.org/api/ng/directive/ngBindHtml

答案 2 :(得分:1)

您应该使用记录在here

的ng-bind-html指令

对于您的代码,它应该如下所示:

<span ng-bind-html='task.dueDate | NormalizeDateTime'></span>

你的控制器也应该有'ngSanitize'作为依赖, 否则你会有例外。

答案 3 :(得分:1)

DOM操作只能在指令中完成,因此使用过滤器是不合适的。

您没有包含任务的示例,因此我假设它看起来像:

{ 
    id: 1, 
    dueDate: new Date( 2014, 5, 13, 13, 30, 0 ), 
    daily: false 
}

任务应该传递给指令而不是dueDate,因为指令需要知道何时显示每日这个词,而这只是一个日期所不能做到的。

这是一个有希望做你想做的指令:

.directive('dueDate', function($filter) {

    return {
        restrict: 'E',
        scope: {
            task: '='
        },
        replace: true,
        template: '<span class="task-duedate"> \
                      <span class="date-daymon">{{daymon}}</span> \
                      <span class="date-year">{{year}}</span> \
                      <span class="date-time">@ {{time}}</span> \
                  </span>',
        link: function(scope){

            if( scope.task.daily ){
                scope.daymon = 'Daily';
            }
            else {
                scope.daymon = $filter('date')(scope.task.dueDate, 'MMM d');
                scope.year = $filter('date')(scope.task.dueDate, 'yyyy');
            }

            scope.time = $filter('date')(scope.task.dueDate, 'h a');
        }
    };
})

用法:

<div ng-repeat='task in tasks'>
   <due-date task='task'></due-date>
</div>

Fiddle

答案 4 :(得分:1)

你去! http://jsfiddle.net/Uv6CP/

让属性中的插值值起作用的技巧是你必须调用iAttrs。$ observe来获取插值。

myApp.directive('duedate', function() {
    return {
        restrict: 'A',
        replace: true,
        template: '<div><span class="date-daymon">{{day}}</span><br><span class="date-year">{{year}}</span><br><span class="date-time">{{time}}</span><br><hr></div>',
        link: function (scope, iElement, iAttrs) {
            iAttrs.$observe('duedate', function(val) {
                console.log("duedate = " + val);
                var parts = val.split('@');
                if (parts.length > 1) {
                    scope.time = parts[1];
                } else {
                    scope.time = "";
                }
                var moreParts = parts[0].split(',');
                if (moreParts.length > 1) {
                    scope.year = moreParts[1];
                } else {
                    scope.year = "";
                }
                scope.day = moreParts[0];
            });
        }
    };
});