Maison >interface Web >js tutoriel >Liaison bidirectionnelle de données de style Bootstrap de listes déroulantes à sélection unique et à sélection multiple implémentées par les directives Angular personnalisées et jQuery_AngularJS
Parlons-en un peu d'abord. Les personnes qui connaissent Angular apprécieront ce plug-in.
00. Mettre la charrue avant les bœufs
Je dois admettre que je suis une personne qui aime mettre la charrue avant les bœufs. Quand j'étais étudiant, j'aimais faire d'abord les devoirs tardifs, laisser les devoirs à rendre bientôt, puis terminer lentement les devoirs sans importance. Bon sang. XX devoirs arrive bientôt, alors dépêche-toi et rattrape-le. Maintenant, je travaille sur ce projet, car je n'ai pas trouvé de plug-in Web déroulant à sélection multiple approprié et je ne voulais pas utiliser le vilain 83e93235161a78387dfc0b11c4aaaabd18bb6ffaf0152bbe49cd8a3620346341 avec HTML, j'ai donc passé une journée entière à en créer un. Peut-être que le temps consacré au développement des fonctions principales de cette manière rendra le développement plus urgent. Je me sens comme un programmeur avec des tendances masochistes et un trouble obsessionnel-compulsif en CSS et en indentation de code.
01. Superflu
Le puissant contrôleur d'Angular semble être capable de répondre à la plupart des besoins de l'interface utilisateur, mais les applications NodeJS utilisent souvent des moteurs de modèles tels que ejs et jade pour générer dynamiquement des pages html. Le problème se pose alors lorsque je veux transmettre l'arrière-plan. Je le fais si les paramètres de res.render() dans express sont directement affichés sur l'interface et liés au modèle ng correspondant ?
Solution 1 : Ne faites pas tout en même temps. Le contrôleur d'Angular peut simplement envoyer une demande de publication, puis obtenir les données
.
Solution 2, utilisez d'abord le modèle pour le stocker temporairement sur le HTML, puis laissez le contrôleur initialiser la valeur de $scope en fonction des données de la page
Solution 3. J'ai peu de connaissances sur Angular et EJS. Quelqu'un peut-il m'apprendre une bonne méthode ?
Par exemple, je souhaite maintenant créer une liste déroulante de sélection 221f08282418e2996498697df914ce4en5a07473c87748fb1bf73f23d45547ab8xx4afa15d3069109ac30911f04c56f333818bb6ffaf0152bbe49cd8a3620346341. Les options sont en arrière-plan. Je ne souhaite pas publier. les séparément, et je ne veux pas non plus les mettre sur la page. Le contrôleur écrit le traitement logique séparément et la communauté Angular dispose d'un plug-in ui-select. Il semble que les données proviennent de $scope, pas directement de <. ;option /> J'étais très populaire à cette époque, pas seulement une liste déroulante, faites-le vous-même.
10. Programmeurs optimistes
L'idée est très claire, définir une directive Angular -> Supprimer la valeur de l'option -> Ajouter divers événements ->
J'ai estimé le temps à une demi-journée, mais je ne peux que deviner combien de temps cela a réellement pris. J'ai du CSS obsessionnel-compulsif, une mauvaise compréhension d'Angular (tant d'opérations HTML utilisent encore jQuery) et une prise en compte insuffisante des événements, ce qui a finalement pris plus de deux fois plus de temps. Terminé,
.
Plus de bêtises, c'est simple et pratique. Vous pouvez soit lier ng-model $scope.xxx à la volée, soit ajuster directement le $("label's id").val() de jQuery pour obtenir la valeur,
Duang du portail Git :
https://git.oschina.net/code2life/easy-select.git
Portail de démonstration duang~duang :
http://ydxxwb.sinaapp.com/easy-select-demo/ (Le code n'est pas le dernier, il y a deux corrections de bugs qui n'ont pas encore été déployées)
11. Notation
angulaire.module('dataDisplay', ['easySelect']).controller('selectController', ['$scope', '$http',function ($scope, $http) { // votre code }]);
Et appelez la boucle $digest() pour laisser Angular mettre à jour le DOM selon ng-model. $digest est l'un des cœurs de la liaison bidirectionnelle d'Angular. Le principe est de synchroniser la valeur de portée modifiée à tous les endroits qui doivent l'être. mis à jour. L'implémentation n'est pas encore grande. Je comprends, j'étudierai ces choses en commençant par $, $$ en Angular quand j'aurai le temps.
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()); }); }); } } } });