カスタム Angular ディレクティブと jQuery_AngularJS によって実装された単一選択および複数選択ドロップダウン ボックスのブートストラップ スタイル データの双方向バインディング

WBOY
リリース: 2016-05-16 15:26:14
オリジナル
1915 人が閲覧しました

まず、Angular に詳しい人はこのプラグインを気に入るはずです。

00。本末転倒です

私は本末転倒な性格であることを認めなければなりませんが、学生の頃は、期限が迫っている宿題を先に終わらせてから、重要ではない宿題をゆっくりと終わらせるのが好きでした。 . くそー、もうすぐ××の宿題が期限だから、急いで補ってくれ。私は現在このプロジェクトに取り組んでいます。適切な複数選択ドロップダウン Web プラグインが見つからず、付属の醜い を使いたくなかったからです。 HTMLなので丸一日かけて作りました。おそらく、このように主要な機能の開発に時間がかかることで、開発の緊急性が高まるでしょう。 CSSやコードのインデントに関しては、私はマゾヒスティックな傾向と強迫性障害を持つプログラマーのような気がします。

01. 余計な

Angular の強力なコントローラーはほとんどの UI ニーズを満たすことができるように見えますが、NodeJS アプリケーションは、HTML ページを動的に生成するために ejs や jade などのテンプレート エンジンを使用することがよくあります。そこで問題が発生します。 Express の res.render() のパラメータがインターフェイスに直接表示され、対応する ng-model にバインドされている場合はそうしますか?

解決策 1: すべてを一度に実行しないでください。Angular のコントローラーは POST リクエストを送信してからデータを取得するだけです。

解決策 2、まずテンプレートを使用して HTML に一時的に保存し、次にコントローラーがページ上のデータに基づいて $scope の値を初期化します

解決策 3. Angular と EJS の知識がほとんどありません。誰か良い方法を教えていただけますか?

たとえば、選択ドロップダウン ボックス を作成したいとします。オプションはバックグラウンドにあります。コントローラーはロジック処理を個別に記述し、Angular コミュニティには ui-select プラグインがあり、データは < から直接取得されるのではなく、$scope から取得されるようです。 ;option /> ドロップダウン ボックス 1 つだけではなく、当時とても人気がありました。

10. 楽観的なプログラマー

アイデアは非常に明確です。Angular ディレクティブを定義します -> さまざまなイベントを追加します -> スコープ データ バインディング -> 所要時間は半日と見積もっていましたが、CSS が強迫的で、Angular の理解が乏しく (非常に多くの HTML 操作で依然として jQuery が使用されている)、イベントについての考慮が不十分でした。最終的には 2 倍以上の時間がかかりました、
もうナンセンスではありません。これはシンプルで実用的です。その場で ng-model $scope.xxx をバインドすることも、jQuery の $("label's id").val() を直接調整して値
を取得することもできます。 Git ポータルの説明:
https://git.oschina.net/code2life/easy-select.git デモポータル duang~duang:
http://ydxxwb.sinaapp.com/easy-select-demo/ (コードは最新ではありません。まだデプロイされていないバグ修正が 2 つあります)

11. 評価

1. 使用方法: ライブラリ ファイル Bootstrap、Angular1.x を導入し、style.css ファイルを導入し (CSS を変更して必要なスタイルをカスタマイズできます)、easy-select.js を導入し、Angular のコントローラーを定義します。 easySelectモジュールはこんな感じ↓

angular.module('dataDisplay', ['easySelect']).controller('selectController', ['$scope', '$http',function ($scope, $http) { // コード }]);

その後は、デモのサンプルの仕様を参照して選択ボックスを定義するだけです。ネイティブ HTML の select タグにはあまり馴染みがありません。


2. ソース コードの説明: DOM 操作とイベントは jQuery で実装されており、各ステップには簡単なコメントが含まれています。双方向バインディングを実現するための鍵は、タグで定義された ng-model を取得し、スコープを設定することです。イベント[ng-model]の値、

そして、$digest() ループを呼び出して、Angular が ng-model に従って DOM を更新できるようにします。$digest は、Angular の双方向バインディングのコアの 1 つであり、変更されたスコープ値を必要なすべての場所に同期します。実装はまだ大きくないので、時間があるときに Angular で $、$$ から勉強してみます。

3. アダプティブと CSS、ブートストラップはアダプティブ、CSS はさまざまなスタイルでカスタマイズ可能、style.css には関連するコメントがあります

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)&#63;"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 &#63; "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 &#63; "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. これが表示された場合は、オプション テンプレートのカスタマイズとオプションのグループ化の 2 つの機能がまだ実装されていないことを意味します。若者よ、オープンソース軍に加わってください。


上記は、カスタム Angular 命令と jQuery によって実装されたブートストラップ スタイルのデータ双方向バインディングを使用してエディターが共有した単一選択および複数選択のドロップダウン ボックスです。気に入っていただければ幸いです。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート