Heim > Web-Frontend > js-Tutorial > Hauptteil

Zwei-Wege-Datenbindung im Bootstrap-Stil von Einzelauswahl- und Mehrfachauswahl-Dropdown-Feldern, implementiert durch benutzerdefinierte Angular-Direktiven und jQuery_AngularJS

WBOY
Freigeben: 2016-05-16 15:26:14
Original
1903 Leute haben es durchsucht

Lassen Sie uns zunächst ein wenig darüber sprechen. Wer mit Angular vertraut ist, wird dieses Plug-in mögen.

00. Das Pferd von hinten aufzäumen

Ich muss zugeben, dass ich ein Mensch bin, der gerne das Pferd von hinten aufzäumt. Als ich Student war, habe ich gerne die späten Hausaufgaben zuerst gemacht, die fälligen Hausaufgaben bald aufgegeben und dann langsam die unwichtigen Hausaufgaben erledigt . Verdammt, die Hausaufgaben sind bald fällig, also beeilen Sie sich und machen Sie sie nach. Jetzt arbeite ich an diesem Projekt, weil ich kein passendes Multi-Select-Dropdown-Web-Plugin finden konnte und ich das hässliche nicht verwenden wollte mit HTML, also habe ich einen ganzen Tag damit verbracht, eines zu erstellen. Möglicherweise erhöht die Zeit, die die Entwicklung der Hauptfunktionen auf diese Weise in Anspruch nimmt, die Entwicklung. Ich fühle mich wie ein Programmierer mit masochistischen Tendenzen und einer Zwangsstörung in CSS und Code-Einrückungen.

01. Überflüssig

Angulars leistungsstarker Controller scheint in der Lage zu sein, die meisten UI-Anforderungen zu erfüllen, aber NodeJS-Anwendungen verwenden häufig Template-Engines wie EJS und Jade, um HTML-Seiten zu generieren. Dann entsteht das Problem, wenn ich den Hintergrund übergeben möchte Was mache ich, wenn die Parameter von res.render() in Express direkt auf der Schnittstelle angezeigt und an das entsprechende NG-Modell gebunden werden?

Lösung 1: Machen Sie nicht alles auf einmal. Der Controller von Angular kann einfach eine Post-Anfrage senden und dann die Daten abrufen

Lösung 2: Verwenden Sie zunächst die Vorlage, um sie vorübergehend im HTML-Code zu speichern, und lassen Sie dann den Controller den Wert von $scope basierend auf den Daten auf der Seite initialisieren


Lösung 3. Ich habe wenig Wissen über Angular und EJS. Kann mir jemand einen guten Weg beibringen?

Jetzt möchte ich zum Beispiel ein Auswahl-Dropdown-Feld erstellen . Die Optionen befinden sich im Hintergrund Ich möchte sie auch nicht separat auf die Seite stellen, und die Angular-Community verfügt über ein UI-Select-Plugin. Es scheint, dass die Daten aus $scope und nicht direkt aus < stammen ;option /> war damals sehr beliebt, nicht nur ein Drop-Down-Feld, es selbst zu machen.

10. Optimistische Programmierer

Die Idee ist sehr klar, definieren Sie eine Angular-Direktive -> Nehmen Sie den Optionswert heraus -> Fügen Sie verschiedene Ereignisse hinzu -> Ich habe die Zeit auf einen halben Tag geschätzt, aber ich kann nur vermuten, wie lange es tatsächlich gedauert hat. Ich habe ein zwanghaftes CSS, ein schlechtes Verständnis von Angular (so viele HTML-Operationen verwenden immer noch jQuery) und eine unzureichende Berücksichtigung von Ereignissen Letztendlich hat es mehr als doppelt so viel Zeit gekostet,

Kein Unsinn mehr, es ist einfach und praktisch. Sie können entweder ng-model $scope.xxx im laufenden Betrieb binden oder jQuerys $("label's id").val() direkt anpassen, um den Wert
zu erhalten Git-Portal hier:
https://git.oschina.net/code2life/easy-select.git
Demoportal duang~duang: http://ydxxwb.sinaapp.com/easy-select-demo/
(Der Code ist nicht der neueste, es gibt zwei Fehlerbehebungen, die noch nicht bereitgestellt wurden)

11. Benotung


1. Verwendung: Führen Sie die Bibliotheksdatei Bootstrap, Angular1.x ein, führen Sie die Datei style.css ein (Sie können das CSS ändern, um den gewünschten Stil anzupassen), easy-select.js, definieren Sie Angulars Controller und Verlassen Sie sich auf das easySelect-Modul. So↓

angle.module('dataDisplay', ['easySelect']).controller('selectController', ['$scope', '$http',function ($scope, $http) { // Ihr Code }]);



Dann beziehen Sie sich einfach auf die Spezifikation des Demo-Beispiels, um das Auswahlfeld zu definieren. Ist es nicht sehr vertraut mit dem nativen HTML-Auswahl-Tag?


2. Erklärung des Quellcodes: DOM-Operationen und -Ereignisse werden mit jQuery implementiert, und jeder Schritt verfügt über einfache Kommentare. Der Schlüssel zum Erreichen einer bidirektionalen Bindung besteht darin, das für das Tag definierte NG-Modell abzurufen und dann den Bereich festzulegen im Ereignis[ ng-model] Wert,

Und rufen Sie die $digest()-Schleife auf, damit Angular das DOM gemäß dem ng-Modell aktualisiert. $digest ist einer der Kerne der bidirektionalen Bindung von Angular. Das Prinzip besteht darin, den geänderten Bereichswert an allen Stellen zu synchronisieren, die erforderlich sind Ich verstehe, dass die Implementierung noch nicht groß ist, ich werde diese Dinge beginnend mit $, $$ in Angular studieren, wenn ich Zeit habe.



3. Adaptiv und CSS, Bootstrap ist adaptiv, CSS kann mit verschiedenen Stilen angepasst werden, style.css hat relevante Kommentare

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());
     });
    });
   }
  }
 }
}); 
Nach dem Login kopieren
100. Wenn Sie dies sehen, bedeutet dies, dass Sie an dieser kleinen Sache interessiert sind. Lassen Sie es uns gemeinsam auf Git verbessern. Die beiden Funktionen zum Anpassen von Optionsvorlagen und zur Optionsgruppierung wurden noch nicht implementiert. Junger Mann, treten Sie der Open-Source-Armee bei.


Das Obige sind die Dropdown-Felder mit Einzelauswahl und Mehrfachauswahl, die der Editor mit benutzerdefinierten Angular-Anweisungen und der bidirektionalen Bindung von Daten im Bootstrap-Stil durch jQuery geteilt hat. Ich hoffe, es gefällt Ihnen.

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage