Angular 输入指令组

很久以前,那时候还不懂写网页。在电视上看到一个外国人说他觉得现在网页太low了,很多东西都只能看,不能改,我要去努力改变这个现状,于是开始学习写代码。

网页可以自己想怎么改就怎么改,确实很有意思。今天由于脑洞一开,把自己的业务也做成了这样。
在这里,主要介绍一下我封装的指令,以及对上面问题的一些思考。

背景:

业务是这样的,我们要开发用户的个人中心页面,一开始是准备做两个页面,一个给用户看,一个给用户编辑。然后,我们考虑到这样好像太麻烦了,最好是让用户想修改啥就修改啥,而不是说看到一整个表单,输入框。然后就像,那我们在每个条目背后添加一个很小的修改按钮,点击修改的话,一开隐藏的输入框就会出现,显示信息的块就会隐藏,如此循环。这样看起来还不错。但是问题又来了,那么多按钮,看起来太奇怪了。那我把修改都去掉,直接让每个信息块都可以点,点一下就切换到可以改的状态。bingo,这个主意不错。于是开始实现了。

分析:

每个信息组有一个初始状态,一个修改状态。

  • 初始状态显示label和span,点击span的话切换到修改状态
  • 修改状态显示label和input,还有保存和取消按钮。保存按钮可以更新修改,然后回到初始状态,取消则是退回到初始状态。

修改结束后,检测表单中的值是否被改变,根据检测值提示用户要不要提交表单。

实现:

        app.directive('inputGroup',function($compile){
            return {
                restrict : 'A',
                require : 'ngModel',
                link : function(scope,element,attrs,ngModel){
                    console.log(scope);
                    var subScope = scope.$new(true);
                    subScope.label = attrs.label;
                    function toggleHiden(params){
                        for(var i in params)
                            params[i] 
                        && params[i].toggleClass 
                        && params[i].toggleClass("hidden");
                    }
                    subScope.save = function(){
                        subScope.value = ngModel.$modelValue;
                        toggleHiden(elements);
                    }
                    subScope.cancel = function(){
                        //取消时,设置输入框的值为原子作用域获取到的值
                        element.val(subScope.value);
                        toggleHiden(elements);
                    }
                    var div = $compile('<div><div>')(subScope);
                    var label = $compile('<label>{{label}}</label>')(subScope);
                    var span = $compile('<span ng-click="save()">{{value|show}}</span>')(subScope);
                    var save = $compile('<button ng-click="save()">保存</button>')(subScope);
                    var cancer = $compile('<button ng-click="cancel()">取消</button>')(subScope);
                    var elements = [element,save,span,cancer];
                    var hiddens = [element,save,cancer];
                    toggleHiden(hiddens);
                    div.attr('class',attrs.classname);
                    element.wrap(div);
                    element.after(label);
                    label.after(element);
                    element.after(span);
                    span.after(save);
                    save.after(cancer);
                    scope.$watch(function(){
                        return true;
                    },function(){
                        subScope.value = ngModel.$modelValue;
                    });
                }
            }
        });

一些辅助的css

        .hidden{
            display:none;
        }
        .anti{

        }
        .anti label{
            display: inline-block;
            width:50px;
        }
        .anti span{
        }
        .anti button{
            margin:5px;
        }
<body ng-app="app" ng-controller="testCtrl as vm">
    <input type="text" ng-model="vm.a" input-group label="用户名" classname="anti">
    <input type="text" ng-model="vm.b" input-group label="用户名" classname="anti">
</body>

效果展示

这里写图片描述

代码分析

inputGroup是一个装饰器型指令,会读取指令上的其他属性如:label、className。并依赖于ngModel指令。
在link函数中,我们利用$compile服务生成了5个活dom。分别添加在input指令的前面、后面、包裹。
为保存按钮绑定toggle事件和更新子作用域。
为取消按钮绑定toggle事件和更新input的值,从而改变model中的值。

存在的问题

1.解决不了的问题:只能适应单个input,不易于扩展。
2.丑陋的语法,由于在创建子作用域的时候,首次获取ngModel.$modelvalue的值是undefined,视图上就显示undefined。我就加了一个$watch,在监控函数中取值,这样好像就能达到在首次取出正确值得目的。但这种做法实在是挫。还需要我再深入学习Angular。

最后

和开头那个人的梦想相比,还差得远,不够由于他的启发,才产生了这样的想法,希望这个指令能让我少写很多代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值