>  기사  >  웹 프론트엔드  >  사용자 정의 Angular 지시문과 jQuery_AngularJS로 구현된 단일 선택 및 다중 선택 드롭다운 상자의 부트스트랩 스타일 데이터 양방향 바인딩

사용자 정의 Angular 지시문과 jQuery_AngularJS로 구현된 단일 선택 및 다중 선택 드롭다운 상자의 부트스트랩 스타일 데이터 양방향 바인딩

WBOY
WBOY원래의
2016-05-16 15:26:141861검색

먼저 Angular에 익숙한 사람들이라면 이 플러그인을 좋아할 것입니다.

00. 말 앞에 수레를 놓는다

저는 학생 시절에는 늦은 숙제부터 먼저 하고, 숙제는 빨리 끝내고, 중요하지 않은 숙제는 천천히 끝내는 걸 좋아하는 사람이었습니다. . 젠장, XX 숙제가 곧 마감이니 서둘러서 보충하세요. 지금 저는 이 프로젝트를 진행하고 있습니다. 적합한 다중 선택 드롭다운 웹 플러그인을 찾을 수 없었고, 제공되는 보기 흉한 6025878462dbd22c14c77f227ef672fa18bb6ffaf0152bbe49cd8a3620346341 기능을 사용하고 싶지 않았기 때문입니다. HTML을 사용했기 때문에 하루 종일 HTML을 만들었습니다. 아마도 이런 식으로 주요 기능을 개발하는 데 소요되는 시간은 개발을 더욱 시급하게 만들 것입니다. 나는 CSS와 코드 들여쓰기에 있어서 마조히즘적 경향과 강박 장애를 가진 프로그래머가 된 것 같은 느낌이 듭니다.

01. 불필요한

Angular의 강력한 컨트롤러는 대부분의 UI 요구 사항을 충족할 수 있는 것처럼 보이지만 NodeJS 애플리케이션은 종종 ejs 및 jade와 같은 템플릿 엔진을 사용하여 HTML 페이지를 동적으로 생성하려고 할 때 문제가 발생합니다. Express의 res.render() 매개변수가 인터페이스에 직접 표시되고 해당 ng-model에 바인딩되면 어떻게 될까요?

해결책 1: 모든 작업을 한꺼번에 수행하지 마세요. Angular의 컨트롤러는 게시 요청을 보낸 다음 데이터를 가져올 수 있습니다.

해결책 2, 먼저 템플릿을 사용하여 HTML에 임시 저장한 다음 컨트롤러가 페이지의 데이터를 기반으로 $scope 값을 초기화하도록 합니다

해결책 3. 저는 Angular와 EJS에 대한 지식이 거의 없습니다. 혹시 좋은 방법을 가르쳐 주실 수 있나요?

예를 들어 이제 선택 드롭다운 상자 221f08282418e2996498697df914ce4en>xx4afa15d3069109ac30911f04c56f333818bb6ffaf0152bbe49cd8a3620346341를 만들고 싶습니다. 옵션은 게시하고 싶지 않습니다. Controller는 로직 처리를 별도로 작성하고 Angular 커뮤니티에는 ui-select 플러그인이 있는 것 같습니다. 데이터는 <에서 직접 가져오는 것이 아닌 것 같습니다. ;option /> 그 당시에는 드롭다운 박스 하나만 있는 것이 아니라 직접 해보면 아주 인기가 많았습니다.

10. 낙관적인 프로그래머

아이디어는 매우 명확합니다. Angular 지시문을 정의합니다. -> 옵션 값 제거 -> 다양한 이벤트 추가 -> 완료
시간은 반나절 정도 걸릴 것으로 예상했지만 실제로 소요된 시간은 대략 짐작할 수 있습니다. 강박적인 CSS가 있고 Angular에 대한 이해가 부족하며(아직 많은 HTML 작업에서 jQuery를 사용함) 이벤트에 대한 고려가 부족합니다. 결국 두 배 이상의 시간이 걸렸습니다.
더 이상 말도 안 되는 일이 아닙니다. 간단하고 실용적입니다. 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의 Controller를 정의하고, easySelect 모듈을 이용해보세요↓
angular.module('dataDisplay', ['easySelect']).controller('selectController', ['$scope', '$http',function ($scope, $http) { // 코드 }]);

그럼 데모 예시의 사양을 참고하여 선택 상자를 정의해 보세요. 기본 HTML 선택 태그와 매우 친숙하지 않나요?

2. 소스 코드 설명: DOM 작업과 이벤트는 jQuery로 구현되며, 각 단계에는 간단한 설명이 있습니다. 양방향 바인딩을 달성하는 핵심은 태그에 정의된 ng-model을 얻은 다음 범위를 설정하는 것입니다. 이벤트[ng-model] 값에서
$digest() 루프를 호출하여 Angular가 ng-model에 따라 DOM을 업데이트하도록 합니다. $digest는 Angular의 양방향 바인딩의 핵심 중 하나입니다. 원칙은 변경된 범위 값을 필요한 모든 위치에 동기화하는 것입니다. 업데이트되었습니다. 아직 구현 규모가 크지는 않습니다. 시간이 나면 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. 이것을 본다면 이 작은 것에 관심이 있다는 뜻입니다. 옵션 템플릿 사용자 정의와 옵션 그룹화라는 두 가지 기능은 아직 구현되지 않았습니다. 젊은이여, 오픈소스 군대에 합류하라.

위는 jQuery로 구현된 사용자 정의 Angular 지침과 Bootstrap 스타일 데이터 양방향 바인딩을 사용하여 편집기에서 공유한 단일 선택 및 다중 선택 드롭다운 상자입니다.

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.