亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

自定義Angular指令與jQuery實(shí)現(xiàn)的Bootstrap風(fēng)格數(shù)據(jù)雙向綁定的單選與多選下拉框

 更新時(shí)間:2015年12月12日 09:13:37   投稿:mrr  
這篇文章主要介紹了自定義Angular指令與jQuery實(shí)現(xiàn)的Bootstrap風(fēng)格數(shù)據(jù)雙向綁定的單選與多選下拉框 的相關(guān)資料,需要的朋友可以參考下

先說點(diǎn)閑話,熟悉Angular的猿們會喜歡這個(gè)插件的。

00.本末倒置

不得不承認(rèn)我是一個(gè)喜歡本末倒置的人,學(xué)生時(shí)代就喜歡先把晚交的作業(yè)先做,留著馬上就要交的作業(yè)不做,然后慢悠悠做完不重要的作業(yè),臥槽,XX作業(yè)馬上要交了,趕緊補(bǔ)補(bǔ)補(bǔ)。如今做這個(gè)項(xiàng)目,因?yàn)闆]找到合適的多選下拉Web插件,又不想用html自帶的丑陋的<select multiple></select>,自己花了一整天時(shí)間做了一個(gè)?;蛟S這樣占用的主要功能開發(fā)的時(shí)間,開發(fā)起來會更有緊迫感吧。感覺自己是個(gè)抖M自虐傾向,并且伴有css和代碼縮進(jìn)強(qiáng)迫癥的程序猿。

01.畫蛇添足

Angular強(qiáng)大的控制器似乎已經(jīng)可以滿足大部分UI上的需求了,但是NodeJS應(yīng)用往往會使用ejs,jade這樣的模板引擎來動態(tài)生成html頁面,那么問題來了,當(dāng)我想把后臺傳給express中res.render()的參數(shù)直接顯示到界面而且綁定到相應(yīng)的ng-model怎么辦?

解決方法1,不要什么事一次來,Angular的Controller發(fā)個(gè)post請求再拿數(shù)據(jù)不就行了

解決方法2,先用模板暫存在html上,再讓Controller根據(jù)頁面上的數(shù)據(jù)來初始化$scope的值

解決方法3,鄙人對Angular和EJS才疏學(xué)淺,誰有好辦法教我唄

比如現(xiàn)在要做一個(gè)選擇下拉框<select>n個(gè)<option>xx</option></select>,選項(xiàng)在后臺,我不想單獨(dú)發(fā)post拿,也不想放在頁面上,Controller單獨(dú)寫邏輯處理,而Angular社區(qū)有個(gè)ui-select插件,看起來數(shù)據(jù)是從$scope取的,并不是直接拿的<option />標(biāo)簽的數(shù)據(jù),當(dāng)時(shí)我就火了,不就一個(gè)下拉框,自己做唄。

10.樂觀的程序猿

思路很明確,定義一個(gè)Angular directive -> 把選項(xiàng)值拿出來 -> 各種事件加加加 -> scope數(shù)據(jù)綁定 -> 完結(jié)撒花
我估計(jì)的時(shí)間是半天,然而實(shí)際花了多久只能呵呵了,css強(qiáng)迫癥,Angular理解不深(所以很多html操作還是在用jQuery),事件考慮不全導(dǎo)致了最終花了超過兩倍的時(shí)間做完,
不廢話了,簡單實(shí)用,既可以即時(shí)綁定ng-model $scope.xxx,也可以直接調(diào)jQuery的$("標(biāo)簽的id").val()也能拿到值,
git傳送門duang:https://git.oschina.net/code2life/easy-select.git
demo傳送門duang~duang:http://ydxxwb.sinaapp.com/easy-select-demo/  (代碼不是最新,有兩個(gè)fix的bug還沒有部署上去)

11.放碼

1.使用方法: 引入庫文件Bootstrap,Angular1.x,引入style.css文件(可以修改css自定義自己想要的樣式),easy-select.js,定義Angular的Controller,依賴easySelect模塊,像這樣 ↓
angular.module('dataDisplay', ['easySelect']).controller('selectController', ['$scope', '$http',function ($scope, $http) {  // your code }]);

然后參考demo示例的規(guī)范定義選擇框就行啦,是不是很有html原生select標(biāo)簽的親切感

2.源碼解釋:dom操作和事件都是用jQuery實(shí)現(xiàn)的,每一步都有簡略的注釋,實(shí)現(xiàn)雙向綁定的關(guān)鍵在于取得標(biāo)簽上定義的ng-model,然后在事件中設(shè)置scope[ng-model]的值,
并且調(diào)用$digest()循環(huán)來讓Angular根據(jù)ng-model更新DOM,$digest是Angular實(shí)現(xiàn)雙向綁定的核心之一,原理是將變化的scope值同步到所有需要更新的地方,實(shí)現(xiàn)暫時(shí)還不大明白,有空單獨(dú)研究一下這些Angular里面$,$$開頭的東西。

3.自適應(yīng)與css,Bootstrap就是自適應(yīng)的,css可以自己定制不同的風(fēng)格,style.css都有相關(guān)注釋

easy-select.js

var comDirective = angular.module('easySelect', []);
comDirective.directive("easySelect", function () {
 return {
  link: function (scope, element, attrs) {
   var ngModel = $(element).attr("ng-model");
   if(!ngModel || ngModel.length == 0) {
    ngModel = "defaultSelectModel";
   }
   var status = false; //toggle boolean
   var valueMap = "";
   var options = $(element).children();
   $(element).attr("style", "padding:0");
   //hide original options
   $.each(options, function (opt) {
    $(options[opt]).attr("style", "display:none");
   });
   //build ul
   var html = "<div id='" + attrs.id + "-root' style='width:100%;position: relative;left:-1px'>" +
    "<p id='display-"+attrs.id + "' style='padding:6px 12px "+ ((attrs.multiple != undefined)?"4px":"7px")+
    " 12px;margin:0;border:none;width:95%;margin-left:2px;background-color: transparent'>" +
    "<span style='display: inline-block;padding-bottom: 3px'> </span></p>" + //this is a dummy span
    "<ul id='" + attrs.id +
    "-container' class='list-group easy-select-container' style='display:none'>"; //options' container
   if(attrs.multiple != undefined) {
    $.each(options, function (opt) {
     html += "<li value='"+ $(options[opt]).val() +"' class='my-li-container list-group-item option-"+
     attrs.id+ "'><div style='width:100%;display:inline-block'>" + $(options[opt]).html() +
     "</div><span value='"+ $(options[opt]).val() +"' class='my-li-option glyphicon glyphicon-ok'></span></li>";
    });
   } else {
    $.each(options, function (opt) {
     if($(options[opt]).attr("default") != undefined) {
      scope[ngModel] = $(options[opt]).val();
      valueMap = $(options[opt]).html();
      html += "<li value='"+ $(options[opt]).val() +"' class='my-li-container list-group-item option-"+ attrs.id+ "'>"
      + $(options[opt]).html() + "</li>";
     } else {
      html += "<li value='"+ $(options[opt]).val() +"' class='my-li-container list-group-item option-"+ attrs.id+ "'>"
      + $(options[opt]).html() + "</li>";
     }
    });
   }
   //if multiple, add button
   if (attrs.multiple != undefined) {
    html += "<li class='list-group-item ' for='ensure-li'><button class='btn btn-default'" +
    " for='ensure-btn' style='padding: 2px' > 確定 </button></li>";
   }
   //render ui
   html += "</ul></div>";
   $(element).append(html);
   $(".my-li-option").each(function(){
    $(this).fadeOut(0);
   });
   if(attrs.multiple == undefined)
    $($("#display-"+attrs.id).children()[0]).html(valueMap);
   //adjust width
   $("#" + attrs.id + "-root").width($("#" + attrs.id + "-root").width() + 2);
   //mouse leave event
   $(element).mouseleave(function(){
    $(".my-li-container").each(function(){
     $(this).attr("style","");
    });
    if(status) {
     $("#" + attrs.id + "-container").attr("style", "display:none");
     status = !status;
    }
   });
   //multiple select seems complex
   if (attrs.multiple != undefined) {
    //click event
    $(element).click(function (e) {
     //if click on tags, remove it
     if($(e.target).attr("for") == "option-tag") {
      // change val and digest change item in angular
      scope[ngModel] = $(element).val().replace($(e.target).attr("value"),"").replace(/;+/,";").replace(/^;/,"");
      $(element).val(scope[ngModel]);
      scope.$digest();
      $(e.target).remove();
      $(".my-li-option").each(function(){
       if($(this).attr("value") == $(e.target).attr("value")) {
        $(this).css("opacity","0.01");
       }
      });
     } else if($(this).attr("for") != 'ensure-li') {
      //toggle ul
      $("#" + attrs.id + "-container").attr("style", status ? "display:none" : "");
      status = !status;
     }
    });
    $(".option-"+attrs.id).each(function(){
     $(this).on('click',function(){
      var selectValue = $(element).val();
      var currentValue = $(this).attr("value");
      var selected = false;
      //if option is selected ,remove it
      var temp = selectValue.split(";");
      $.each(temp,function(obj){
       if(temp[obj].indexOf(currentValue) != -1) {
        selected = true;
       }
      })
      if(selected) {
       $($(this).children()[1]).fadeTo(300,0.01);
       scope[ngModel] = $(element).val().replace(currentValue,"").replace(/;{2}/,";").replace(/^;/,"");
       $(element).val(scope[ngModel]);
       scope.$digest();
       $("#display-"+attrs.id + " span").each(function(){
        if($(this).attr("value") == currentValue) {
         $(this).remove();
        }
       });
      } else {
       //add option to val() and ui
       $($(this).children()[1]).fadeTo(300,1);
       scope[ngModel] = ($(element).val()+";"+currentValue).replace(/;{2}/,";").replace(/^;/,"");
       $(element).val(scope[ngModel]);
       scope.$digest();
       $("#display-"+attrs.id).append(
        "<span for='option-tag' value='"+ $(this).attr("value") +"' class='p-option-tag'>"
        +$(this).children()[0].innerHTML+ "</span>");
      }
      status = !status; // prevent bubble
     });
     //control background
     $(this).mouseenter(function(){
      $(".my-li-container").each(function(){
       $(this).attr("style","");
      });
      $(this).attr("style","background-color:#eee");
     });
    });
   } else {
    $(".option-"+attrs.id).each(function(){
     $(this).mouseenter(function(){
      $(".my-li-container").each(function(){
       $(this).attr("style","");
      });
      $(this).attr("style","background-color:#eee");
     });
    });
    //single select ,just add value and remove ul
    $(element).click(function () {
     $("#" + attrs.id + "-container").attr("style", status ? "display:none" : "");
     status = !status;
    });
    $(".option-"+attrs.id).each(function(){
     $(this).on('click',function(){
      scope[ngModel] = $(this).attr("value");
      $(element).val(scope[ngModel]);
      scope.$digest();
      console.log(ngModel);
      console.log(element.val());
      $($("#display-"+attrs.id).children()[0]).html($(this).html());
     });
    });
   }
  }
 }
}); 

 100.如果看到了這里,說明對這個(gè)小東西有興趣,git上一起完善吧,自定義選項(xiàng)模板,選項(xiàng)分組這兩個(gè)功能還沒有實(shí)現(xiàn)。少年,加入開源的大軍吧。

以上所述是小編給大家分享的自定義Angular指令與jQuery實(shí)現(xiàn)的Bootstrap風(fēng)格數(shù)據(jù)雙向綁定的單選與多選下拉框,希望大家喜歡。

相關(guān)文章

  • RequireJS 依賴關(guān)系的實(shí)例(推薦)

    RequireJS 依賴關(guān)系的實(shí)例(推薦)

    下面小編就為大家?guī)硪黄猂equireJS 依賴關(guān)系的實(shí)例(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-01-01
  • Angular中的NgZone.run()有什么用途

    Angular中的NgZone.run()有什么用途

    在Angular中,NgZone是一個(gè)服務(wù),用于管理異步任務(wù)的執(zhí)行,并提供一種在Angular區(qū)域內(nèi)或外部顯式運(yùn)行代碼的方式,NgZone.run方法是一種顯式在Angular區(qū)域內(nèi)運(yùn)行函數(shù)的方式,本文介紹Angular中的NgZone.run()有什么用,感興趣的朋友一起看看吧
    2024-01-01
  • angular.js實(shí)現(xiàn)列表orderby排序的方法

    angular.js實(shí)現(xiàn)列表orderby排序的方法

    今天小編就為大家分享一篇angular.js實(shí)現(xiàn)列表orderby排序的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-10-10
  • Angular2.js實(shí)現(xiàn)表單驗(yàn)證詳解

    Angular2.js實(shí)現(xiàn)表單驗(yàn)證詳解

    這篇文章主要介紹了Angular2.js實(shí)現(xiàn)表單驗(yàn)證的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • 強(qiáng)大的 Angular 表單驗(yàn)證功能詳細(xì)介紹

    強(qiáng)大的 Angular 表單驗(yàn)證功能詳細(xì)介紹

    本篇文章主要介紹了強(qiáng)大的 Angular 表單驗(yàn)證功能詳細(xì)介紹,使用 Angular 的內(nèi)置表單校驗(yàn)?zāi)軌蛲瓿山^大多數(shù)的業(yè)務(wù)場景的校驗(yàn)需求,有興趣的可以了解一下
    2017-05-05
  • protractor的安裝與基本使用教程

    protractor的安裝與基本使用教程

    這篇文章主要給大家介紹了關(guān)于protractor安裝與基本使用的相關(guān)資料,文中介紹的非常詳細(xì),對大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。
    2017-07-07
  • AngularJS 異步解決實(shí)現(xiàn)方法

    AngularJS 異步解決實(shí)現(xiàn)方法

    這篇文章主要介紹了AngularJS 異步解決實(shí)現(xiàn)方法的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • 深入理解AngularJS中的ng-bind-html指令

    深入理解AngularJS中的ng-bind-html指令

    ng-bind-html和ng-bind的區(qū)別就是,ng-bind把值作為字符串,和元素的內(nèi)容進(jìn)行綁定,但是ng-bind-html把值作為html,和元素的html進(jìn)行綁定.相當(dāng)于jq里面的.text()和.html()。這篇文章主要給大家深入的介紹了AngularJS中ng-bind-html指令 的相關(guān)資料,需要的朋友可以參考下。
    2017-03-03
  • angularJs中orderBy篩選以及filter過濾數(shù)據(jù)的方法

    angularJs中orderBy篩選以及filter過濾數(shù)據(jù)的方法

    今天小編就為大家分享一篇angularJs中orderBy篩選以及filter過濾數(shù)據(jù)的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-09-09
  • Angular模版驅(qū)動表單的使用總結(jié)

    Angular模版驅(qū)動表單的使用總結(jié)

    這篇文章主要介紹了Angular模版驅(qū)動表單的使用總結(jié),本文實(shí)現(xiàn)了Angular支持表單的雙向數(shù)據(jù)綁定,校驗(yàn),狀態(tài)管理,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2018-05-05

最新評論