<!DOCTYPE html>
<html>
  <head>
    <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-select/0.13.2/select.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/3.4.5/select2.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.8.5/css/selectize.default.css">
    <!--<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.8.5/css/selectize.bootstrap3.css">-->
    <link data-require="intl-tel-input@*" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/intl-tel-input/7.0.2/css/intlTelInput.css" />
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <div class="container content" ng-controller="MainController as app">
      <lc-edit-preview class="lc-edit-preview" name="address"></lc-edit-preview>
      <lc-edit-preview class="lc-edit-preview" name="phone"></lc-edit-preview>
      <lc-edit-preview class="lc-edit-preview" name="email"></lc-edit-preview>
      <lc-edit-preview class="lc-edit-preview" name="website"></lc-edit-preview>
      <lc-edit-preview class="lc-edit-preview" name="type"></lc-edit-preview>
      <lc-edit-preview class="lc-edit-preview" name="category"></lc-edit-preview>
      <lc-edit-preview class="lc-edit-preview" name="location"></lc-edit-preview>
    </div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <script data-require="intl-tel-input@*" src="https://cdnjs.cloudflare.com/ajax/libs/intl-tel-input/7.0.2/js/intlTelInput.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/api-check/7.5.5/api-check.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular-sanitize.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-formly/7.3.9/formly.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-select/0.13.2/select.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-formly-templates-bootstrap/6.2.0/angular-formly-templates-bootstrap.min.js"></script>
    <script src="js/international-phone-number.js"></script>
    <script src="app.js"></script>
  </body>
</html>
(function (ng, doc) {
  "use strict";
  var config, appName, MainController, lcEditPreviewController, lcEditPreviewDirective;
  appName        = "app";
  config         = function configF(formlyConfigProvider) {
    var formlyTypes, formlyWrappers;
    formlyTypes    = [
        {
          overwriteOk:    true,
          name:           "input",
          templateUrl:    "tpls/input_formly.html",
          defaultOptions: {templateOptions: {required: true, minlength: 3, maxlength: 100}}
        },
        {
          overwriteOk:    true,
          name:           "phone",
          templateUrl:    "tpls/input_phone_formly.html",
          defaultOptions: {templateOptions: {required: true}}
        },
        {
          overwriteOk:  true,
          name:         "ui-select-single",
          templateUrl:  "tpls/formly_ui_select_single.min.html",
          defaultOptions: {
            templateOptions: {
              required:    true,
              valueProp:   "id",
              labelProp:   "name",
              optionsAttr: "bs-options",
              ngOptions:   "option[to.valueProp] as option in to.options | filter: $select.search"
            }
          }
        },
        {
          overwriteOk:  true,
          name: 'ui-select-single-search',
          templateUrl: 'tpls/ui-select-single-async-search.html',
          defaultOptions: {
            templateOptions: {
              required:    true,
              optionsAttr: "bs-options",
              ngOptions:   "option[to.valueProp] as option in to.options | filter: $select.search"
            }
          }
        }
    ];
    formlyWrappers = [
      {
        types: ["input", "phone"],
        templateUrl: "tpls/input_formly_wrapper.html"
      },
      {
        types:       ["inputWithLabel", "ui-select-single", "ui-select-single-search"],
        templateUrl:  "tpls/formly_input_wrapper_with_label.min.html"
      },
    ];
    formlyConfigProvider.setType(formlyTypes);
    formlyConfigProvider.setWrapper(formlyWrappers);
  };
  MainController = function MainControllerF() {
    var app;
    app = this;
  };
  lcEditPreviewDirective = function lcEditPreviewDirective(TPLS_ASSETS) {
    return {
      scope:            {},
      restrict:         "E",
      controllerAs:     "lcEditPreview",
      controller:       "lcEditPreviewController",
      templateUrl:      TPLS_ASSETS + '/lc_edit_preview.min.html',
      bindToController: {
        name: "@"
      }
    };
  };
  lcEditPreviewController = function lcEditPreviewController($http, $q) {
    var lcEditPreview, categories, locations, validateUrl, refreshAddresses;
    lcEditPreview        = this;
    lcEditPreview.page   = {};
    categories           = [
      {id: 1, name: 'Clothing'},
      {id: 2, name: 'Sport'},
      {id: 3, name: 'Electronic'},
      {id: 4, name: 'Decration'},
      {id: 5, name: 'Garden'}
    ];
    locations            = [
      {id: 1, name: 'International'},
      {id: 2, name: 'France'},
      {id: 3, name: 'Tunisia'},
      {id: 4, name: 'Belgium'},
      {id: 5, name: 'Italy'}
    ];
    refreshAddresses     = function refreshAddresses(address, field) {
      var promise;
      if (!address) {
        promise = $q.when({data: {results: []}});
      } else {
        var params = {address: address, sensor: false};
        var endpoint = '//maps.googleapis.com/maps/api/geocode/json';
        promise = $http.get(endpoint, {params: params});
      }
      return promise.then(function(response) {
        field.templateOptions.options = response.data.results;
      });
    };
    validateUrl          = function validateUrlF($viewValue, $modelValue, scope) {
      return ($modelValue || $viewValue) ? /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?\/$/i.test( value ) : true;
    };
    lcEditPreview.fields = {
      address: [
        {
          key: 'address',
          type: 'ui-select-single-search',
          className: 'col-lg-6',
          templateOptions: {
            optionsAttr: 'bs-options',
            ngOptions: 'option[to.valueProp] as option in to.options | filter: $select.search',
            label: 'Address',
            valueProp: 'formatted_address',
            labelProp: 'formatted_address',
            placeholder: 'Your address',
            options: [],
            refresh: refreshAddresses,
            refreshDelay: 0
          }
        }
      ],
     phone: [
        {
          key: 'phone',
          type: 'phone',
          className: 'col-lg-6',
          templateOptions: {
            label: 'Phone',
            type: 'text',
            placeholder: 'Your phone'
          }
        }
      ],
      email: [
        {
          key: 'email',
          type: 'input',
          className: 'col-lg-6',
          templateOptions: {
            label: 'Email',
            type: 'email',
            placeholder: 'example@example.com'
          }
        }
      ],
      website: [
        {
          key:        'website',
          type:       'input',
          className:  'col-lg-6',
          validators: {url: validateUrl},
          templateOptions: {
            label: 'Website',
            type: 'text',
            placeholder: 'Your website'
          }
        }
      ],
      type: [
        {
          key:        'type',
          type:       'input',
          className:  'col-lg-6',
          templateOptions: {
            label: 'Type',
            type: 'text',
            placeholder: 'Your type'
          }
        }
      ],
      category: [
        {
          key:             "category",
          type:            "ui-select-single",
          className:       'col-lg-6',
          templateOptions: {
            label:       "Category",
            options:     categories,
            placeholder: "Choose a cetegory"
          }
        }
      ],
      location: [
        {
          key:             "location",
          type:            "ui-select-single",
          className:      'col-lg-6',
          templateOptions: {
            label:       "Location",
            options:     locations,
            placeholder: "Choose a location"
          }
        }
      ]
    };
  };
  ng.module(appName, ['formly', 'formlyBootstrap', 'ngSanitize', 'ui.select', 'internationalPhoneNumber'], config)
    .constant("TPLS_ASSETS", "tpls")
    .controller("MainController", MainController)
    .directive("lcEditPreview", lcEditPreviewDirective)
    .controller("lcEditPreviewController", lcEditPreviewController);
  ng.bootstrap(doc, [appName]);
}(angular, document));
.lc-reset-padding-v {
  padding-left: 0;
  padding-right: 0;
}
body {
  background-color: #f6f6f6;
}
.content {
  margin-top: 100px;
  text-align: center;
}
.lc-edit-preview {
  display: block;
  margin-bottom: 30px;  
}
.formly-field,
div[ng-transclude] {
  display: inline-block;
}
.form-inline table {
  margin-bottom: 0;
}
.form-inline table tr > td {
  padding: 5px 10px 0;
}
.form-inline .control-label {
  line-height: 30px;
}
.form-inline .form-control,
.form-inline .selectize-control,
.form-inline .ui-select-bootstrap {
  display: inline-block;
}
.select2 > .select2-choice.ui-select-match {
  /* Because of the inclusion of Bootstrap */
  height: 29px;
}
.selectize-control > .selectize-dropdown {
  top: 36px;
}
.ui-select-bootstrap > .ui-select-match > .btn {
  max-width: 100%;
  width: 230px;
}
<form
  novalidate
  name="UpdateForm"
  autocomplete="off"
  class="row form-inline"
  ng-if="lcEditPreview.isEditMode"
>
  <formly-form
    class="col-lg-6 col-lg-offset-3"
    model="lcEditPreview.page"
    fields="lcEditPreview.fields[lcEditPreview.name]"
  >
    <div class="form-group">
      <button
        type="button"
        ng-disabled="UpdateForm.$invalid"
        class="btn btn-small btn-primary"
        ng-click="lcEditPreview.update(lcEditPreview.name, lcEditPreview[lcEditPreview.name])"
      >
        Confirm
      </button>
      <button
        type="reset"
        class="btn btn-small btn-danger"
        ng-click="lcEditPreview.isEditMode=false"
      >
        Cancel
      </button>
    </div>
  </formly-form>
</form>
<div class="lc-preview" ng-if="!lcEditPreview.isEditMode">
  {{lcEditPreview.page[lcEditPreview.fields[lcEditPreview.name].key]}}
  <button class="btn btn-primary btn-sm" ng-click="lcEditPreview.isEditMode=true">Edit</button>
</div>
<div
  class="formly-template-wrapper pull-left form-group"
  ng-class="{
    'has-success': form[id].$valid,
    'has-error': options.validation.errorExistsAndShouldBeVisible
  }"
>
  <label for="{{id}}" class="col-lg-4 control-label lc-reset-padding-v">
    {{to.label}} {{to.required ? '*' : ''}}
  </label>

  <div class="col-lg-8 text-right lc-reset-padding-v">
    <label
      ng-messages="fc.$error"
      class="validation help-block"
      ng-if="options.validation.errorExistsAndShouldBeVisible"
    >
      <div ng-messages-include="tpls/validation.min.html"></div>
      <div
        ng-message="{{::name}}"
        ng-repeat="(name, message) in ::options.validation.messages track by $index"
      >
        {{message(fc.$viewValue, fc.$modelValue, this)}}
      </div>
    </label>
    <formly-transclude></formly-transclude>
  </div>
</div>
<input
  id="{{id}}"
  class="form-control"
  formly-dynamic-name="id"
  ng-disabled="to.disabled"
  ng-required="to.required"
  type="{{to.type || 'text'}}"
  ng-model="model[options.key]"
  placeholder="{{to.placeholder}}"
  aria-describedby="{{id}}_description"
  formly-custom-validation="options.validators"
>
<ui-select
  theme="selectize"
  disabled="{{to.disabled}}"
  required="{{to.required}}"
  ng-model="model[options.key]"
>
  <ui-select-match placeholder="{{to.placeholder}}">
    {{$select.selected[to.labelProp]}}
  </ui-select-match>
  <ui-select-choices data-repeat="{{to.ngOptions}}">
    <div ng-bind-html="option[to.labelProp] | highlight: $select.search"></div>
  </ui-select-choices>
</ui-select>
<div
  class="formly-template-wrapper pull-left form-group"
  ng-class="{
    'has-success': form[id].$valid,
    'has-error': options.validation.errorExistsAndShouldBeVisible
  }"
>
  <label for="{{id}}" class="col-lg-4 control-label lc-reset-padding-v">
    {{to.label}} {{to.required ? '*' : ''}}
  </label>
  <div class="col-lg-8 lc-reset-padding-v">
    <label
      ng-messages="fc.$error"
      class="validation help-block"
      ng-if="options.validation.errorExistsAndShouldBeVisible"
    >
      <div ng-messages-include="assets/tpls/validation.min.html"></div>
      <div
        ng-message="{{::name}}"
        ng-repeat="(name, message) in ::options.validation.messages track by $index"
      >
        {{message(fc.$viewValue, fc.$modelValue, this)}}
      </div>
    </label>
    <formly-transclude></formly-transclude>
  </div>
</div>
<div ng-message="required">{{to.label}} is required.</div>
<div ng-message="email">{{to.label}} is Invalid.</div>
<div ng-message="minlength, maxlength">
  {{to.label}} must be between {{to.minlength}} and {{to.maxlength}}.
</div>
<div ng-message="fieldMatch">Passwords should match.</div>
<input
  id="{{id}}"
  class="form-control"
  formly-dynamic-name="id"
  ng-disabled="to.disabled"
  ng-required="to.required"
  type="{{to.type || 'text'}}"
  ng-model="model[options.key]"
  placeholder="{{to.placeholder}}"
  aria-describedby="{{id}}_description"
  formly-custom-validation="options.validators"
  international-phone-number
>
<ui-select
  theme="bootstrap"
  reset-search-input="false"
  ng-model="model[options.key]"
  ng-required="{{to.required}}"
  ng-disabled="{{to.disabled}}"
>
  <ui-select-match placeholder="{{to.placeholder}}">{{$select.selected[to.labelProp]}}</ui-select-match>
  <ui-select-choices
    repeat="{{to.ngOptions}}"
    refresh="to.refresh($select.search, options)"
    refresh-delay="{{to.refreshDelay}}"
  >
    <div ng-bind-html="option[to.labelProp] | highlight: $select.search"></div>
    <div><small>{{option.geometry.location.lat}}, {{option.geometry.location.lng}}</small></div>
  </ui-select-choices>
</ui-select>
(function() {
  "use strict";
  angular.module("internationalPhoneNumber", []).constant('ipnConfig', {
    allowExtensions: false,
    autoFormat: true,
    autoHideDialCode: true,
    autoPlaceholder: true,
    customPlaceholder: null,
    defaultCountry: "",
    geoIpLookup: null,
    nationalMode: true,
    numberType: "MOBILE",
    onlyCountries: void 0,
    preferredCountries: ['us', 'gb'],
    skipUtilScriptDownload: false,
    utilsScript: ""
  }).directive('internationalPhoneNumber', [
    '$timeout', 'ipnConfig', function($timeout, ipnConfig) {
      return {
        restrict: 'A',
        require: '^ngModel',
        scope: {
          ngModel: '=',
          country: '='
        },
        link: function(scope, element, attrs, ctrl) {
          var handleWhatsSupposedToBeAnArray, options, read, watchOnce;
          if (ctrl) {
            if (element.val() !== '') {
              $timeout(function() {
                element.intlTelInput('setNumber', element.val());
                return ctrl.$setViewValue(element.val());
              }, 0);
            }
          }
          read = function() {
            return ctrl.$setViewValue(element.val());
          };
          handleWhatsSupposedToBeAnArray = function(value) {
            if (value instanceof Array) {
              return value;
            } else {
              return value.toString().replace(/[ ]/g, '').split(',');
            }
          };
          options = angular.copy(ipnConfig);
          angular.forEach(options, function(value, key) {
            var option;
            if (!(attrs.hasOwnProperty(key) && angular.isDefined(attrs[key]))) {
              return;
            }
            option = attrs[key];
            if (key === 'preferredCountries') {
              return options.preferredCountries = handleWhatsSupposedToBeAnArray(option);
            } else if (key === 'onlyCountries') {
              return options.onlyCountries = handleWhatsSupposedToBeAnArray(option);
            } else if (typeof value === "boolean") {
              return options[key] = option === "true";
            } else {
              return options[key] = option;
            }
          });
          watchOnce = scope.$watch('ngModel', function(newValue) {
            return scope.$$postDigest(function() {
              if (newValue !== null && newValue !== void 0 && newValue.length > 0) {
                if (newValue[0] !== '+') {
                  newValue = '+' + newValue;
                }
                ctrl.$modelValue = newValue;
              }
              element.intlTelInput(options);
              if (!(options.skipUtilScriptDownload || attrs.skipUtilScriptDownload !== void 0 || options.utilsScript)) {
                element.intlTelInput('loadUtils', '/bower_components/intl-tel-input/lib/libphonenumber/build/utils.js');
              }
              return watchOnce();
            });
          });
          scope.$watch('country', function(newValue) {
            if (newValue !== null && newValue !== void 0 && newValue !== '') {
              return element.intlTelInput("selectCountry", newValue);
            }
          });
          ctrl.$formatters.push(function(value) {
            if (!value) {
              return value;
            }
            element.intlTelInput('setNumber', value);
            return element.val();
          });
          ctrl.$parsers.push(function(value) {
            if (!value) {
              return value;
            }
            return value.replace(/[^\d]/g, '');
          });
          ctrl.$validators.internationalPhoneNumber = function(value) {
            var selectedCountry;
            selectedCountry = element.intlTelInput('getSelectedCountryData');
            if (!value || (selectedCountry && selectedCountry.dialCode === value)) {
              return true;
            }
            return element.intlTelInput("isValidNumber");
          };
          element.on('blur keyup change', function(event) {
            return scope.$apply(read);
          });
          return element.on('$destroy', function() {
            element.intlTelInput('destroy');
            return element.off('blur keyup change');
          });
        }
      };
    }
  ]);

}).call(this);