ホームページ >ウェブフロントエンド >jsチュートリアル >カスタム Angular ディレクティブと jQuery_AngularJS によって実装された単一選択および複数選択ドロップダウン ボックスのブートストラップ スタイル データの双方向バインディング
まず、Angular に詳しい人はこのプラグインを気に入るはずです。
00。本末転倒です
私は本末転倒な性格であることを認めなければなりませんが、学生の頃は、期限が迫っている宿題を先に終わらせてから、重要ではない宿題をゆっくりと終わらせるのが好きでした。 . くそー、もうすぐ××の宿題が期限だから、急いで補ってくれ。私は現在このプロジェクトに取り組んでいます。適切な複数選択ドロップダウン Web プラグインが見つからず、付属の醜い 83e93235161a78387dfc0b11c4aaaabd18bb6ffaf0152bbe49cd8a3620346341 を使いたくなかったからです。 HTMLなので丸一日かけて作りました。おそらく、このように主要な機能の開発に時間がかかることで、開発の緊急性が高まるでしょう。 CSSやコードのインデントに関しては、私はマゾヒスティックな傾向と強迫性障害を持つプログラマーのような気がします。
01. 余計な
Angular の強力なコントローラーはほとんどの UI ニーズを満たすことができるように見えますが、NodeJS アプリケーションは、HTML ページを動的に生成するために ejs や jade などのテンプレート エンジンを使用することがよくあります。そこで問題が発生します。 Express の res.render() のパラメータがインターフェイスに直接表示され、対応する ng-model にバインドされている場合はそうしますか?
解決策 1: すべてを一度に実行しないでください。Angular のコントローラーは POST リクエストを送信してからデータを取得するだけです。
解決策 2、まずテンプレートを使用して HTML に一時的に保存し、次にコントローラーがページ上のデータに基づいて $scope の値を初期化します
解決策 3. Angular と EJS の知識がほとんどありません。誰か良い方法を教えていただけますか?
たとえば、選択ドロップダウン ボックス 221f08282418e2996498697df914ce4en5a07473c87748fb1bf73f23d45547ab8xx4afa15d3069109ac30911f04c56f333818bb6ffaf0152bbe49cd8a3620346341 を作成したいとします。オプションはバックグラウンドにあります。コントローラーはロジック処理を個別に記述し、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. 評価
angular.module('dataDisplay', ['easySelect']).controller('selectController', ['$scope', '$http',function ($scope, $http) { // コード }]);
そして、$digest() ループを呼び出して、Angular が ng-model に従って DOM を更新できるようにします。$digest は、Angular の双方向バインディングのコアの 1 つであり、変更されたスコープ値を必要なすべての場所に同期します。実装はまだ大きくないので、時間があるときに Angular で $、$$ から勉強してみます。
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()); }); }); } } } });