Search code examples
angularangular7dropdownselect-options

Custom HTML select option with Angular 7 is not working


Today I am trying to make a custom select dropdown with Angular 7 and it's working fine when i putting static value in select options. But problem is when I am trying to use Angular *ngFor loop or *ngIf, Then the customisation is not working. Please see my HTML, CSS and Javascript code below.

HTML Working

<select class="selectOp" id="creator">
    <option value="hide">Select Creator</option>
    <option value="2010">Adam</option>
    <option value="2011">Imran</option>
    <option value="2012">Salma</option>
    <option value="2013">Noor</option>
    <option value="2014">Jamal</option>
    <option value="2015">Hasan</option>
  </select>

HTML Not Working in Angular *ngFor

<select class="selectOp">
  <option *ngFor="let contentype of dataScoruc.contentype">
    {{contentype}}
  </option>
</select>

TS

  ngOnInit() {
    this.dropDownFunc();
  }

  dropDownFunc(){

    $('.selectOp').each(function(){
        var $this = $(this), numberOfOptions = $(this).children('option').length;

        $this.addClass('select-hidden'); 
        $this.wrap('<div class="select"></div>');
        $this.after('<div class="select-styled"></div>');

        var $styledSelect = $this.next('div.select-styled');
        $styledSelect.text($this.children('option').eq(0).text());

        var $list = $('<ul />', {
            'class': 'select-options'
        }).insertAfter($styledSelect);

        for (var i = 0; i < numberOfOptions; i++) {
            $('<li />', {
                text: $this.children('option').eq(i).text(),
                rel: $this.children('option').eq(i).val()
            }).appendTo($list);
        }

        var $listItems = $list.children('li');

        $styledSelect.click(function(e) {
            e.stopPropagation();
            $('div.select-styled.active').not(this).each(function(){
                $(this).removeClass('active').next('ul.select-options').hide();
            });
            $(this).toggleClass('active').next('ul.select-options').toggle();
        });

        $listItems.click(function(e) {
            e.stopPropagation();
            $styledSelect.text($(this).text()).removeClass('active');
            $this.val($(this).attr('rel'));
            $list.hide();
            //console.log($this.val());
        });

        $(document).click(function() {
            $styledSelect.removeClass('active');
            $list.hide();
        });

    });
  }

CSS

.select-hidden {
  display: none;
  visibility: hidden;
  padding-right: 10px;
}
.select {
  cursor: pointer;
  display: inline-block;
  position: relative;
  font-size: 14px;
  color: #4d4d4d;
  width: 100%;
  height: auto;
}
.select-styled {
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background-color: white;
  padding: 4px 15px;
  border: 1px solid #dfdfdf;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 500;
}
.select-styled:after {
  content:"";
  width: 0;
  height: 0;
  border: 5px solid transparent;
  border-color: #4D4D4D transparent transparent transparent;
  position: absolute;
  top: 14px;
  right: 10px;
}
.select-options {
  display: none; 
  position: absolute;
  top: 100%;
  right: 0;
  left: 0;
  z-index: 999;
  margin: 0;
  padding: 0;
  list-style: none;
  background-color: #ffffff;
  border: 1px solid #dededf;
  border-radius: 4px;

}
.select-options li {
  margin: 0;
  padding: 4px 0;
  text-indent: 15px;
  font-size: 12px;
  font-weight: 500;
}
.select-options li:hover {
  color: #000000;
  font-weight: 500;
  font-style: italic;
}
.select-options li [rel="hide"] {
  display: none;
}

Please everybody check it and put your suggestion please.


Solution

  • The JQuery code is executing before angular rendering its option tags

    you need to call this.dropDownFunc() after angular finish it's rendering job, so you can call it from ngAfterViewInit instead of ngOnInit

    in order to use ngAfterViewInit you may need to import its interface from @angular/core

    import { Component , AfterViewInit} from '@angular/core';

    and implements it with AppComponent class

    export class AppComponent extends Component implements AfterViewInit{

    Here full source code

    import { Component ,  AfterViewInit} from '@angular/core';
    import $ from "jquery";
    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html',
      styleUrls: [ './app.component.css' ]
    })
    export class AppComponent  extends Component implements AfterViewInit{
      dataScoruc={
        contentype:[
          'AAAAA',
          'BBBB',
          'CCCC',
          'DDDD',
          'EEEE',
          'FFFFF',
        ]
      }
      ngOnInit() {
        // this.dropDownFunc();
      }
       ngAfterViewInit(){
        this.dropDownFunc();
      }
    
    
    
      dropDownFunc(){
    
        $('.selectOp').each(function(){
            var $this = $(this), numberOfOptions = $(this).children('option').length;
    
            $this.addClass('select-hidden'); 
            $this.wrap('<div class="select"></div>');
            $this.after('<div class="select-styled"></div>');
    
            var $styledSelect = $this.next('div.select-styled');
            $styledSelect.text($this.children('option').eq(0).text());
    
            var $list = $('<ul />', {
                'class': 'select-options'
            }).insertAfter($styledSelect);
    
            for (var i = 0; i < numberOfOptions; i++) {
                $('<li />', {
                    text: $this.children('option').eq(i).text(),
                    rel: $this.children('option').eq(i).val()
                }).appendTo($list);
            }
    
            var $listItems = $list.children('li');
    
            $styledSelect.click(function(e) {
                e.stopPropagation();
                $('div.select-styled.active').not(this).each(function(){
                    $(this).removeClass('active').next('ul.select-options').hide();
                });
                $(this).toggleClass('active').next('ul.select-options').toggle();
            });
    
            $listItems.click(function(e) {
                e.stopPropagation();
                $styledSelect.text($(this).text()).removeClass('active');
                $this.val($(this).attr('rel'));
                $list.hide();
                //console.log($this.val());
            });
    
            $(document).click(function() {
                $styledSelect.removeClass('active');
                $list.hide();
            });
    
        });
      }
    }
    

    and working demo (https://stackblitz.com/edit/angular-jq-dummy-select)