Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS: can't change input type

Tags:

angularjs

Whenver I have an Angular expression as a value to input's type, it won't work:

<input ng-model="model" type="{{'number'}}">

Numeric values get converted to strings and checkboxes won't work at all.

http://jsfiddle.net/punund/NRRj7/3/

like image 752
punund Avatar asked Mar 01 '13 00:03

punund


5 Answers

yes you can ... at least now :)

HTML:

<section ng-app="myApp" ng-controller="mainCtrl">
  <input type="{{inputType}}" placeholder="Put your password" />
  <input type="checkbox" id="checkbox" ng-model="passwordCheckbox" ng-click="hideShowPassword()" />
  <label for="checkbox" ng-if="passwordCheckbox">Hide password</label>
  <label for="checkbox" ng-if="!passwordCheckbox">Show password</label>  
</section>
<script src="http://code.angularjs.org/1.2.13/angular.min.js"></script>

JS:

var myApp = angular.module('myApp', []);
myApp.controller('mainCtrl', ['$scope', function( $scope ){

  // Set the default value of inputType
  $scope.inputType = 'password';

  // Hide & show password function
  $scope.hideShowPassword = function(){
    if ($scope.inputType == 'password')
      $scope.inputType = 'text';
    else
      $scope.inputType = 'password';
  };
}]);

source: http://codepen.io/gymbry/pen/fJchw/

UPDATE 17/04/2015:

I have randomly changed Angular version in above Codepen and this seems to work from version 1.0.2 ... Hope this help ...

like image 200
vidriduch Avatar answered Oct 22 '22 12:10

vidriduch


You can't change input's type dynamically since IE disallows this and AngularJS needs to be cross-browser compatible. So even if you might see the changed type displayed in the source code AngularJS won't pick it up - type is only evaluated once and can't be changed.

Please note that the same restriction applies to jQuery: jQuery change input type

You only options for dynamic types are either a custom directive (where you can download a dynamic template or prepare DOM on-the-fly) or using ng-include to include include partials where the input type is a static value.

like image 39
pkozlowski.opensource Avatar answered Oct 22 '22 12:10

pkozlowski.opensource


You cannot change the input type dynamically in any browser and so it is not possible to use dynamic single input statement. You are left with using conditional statement for creation of elements where type is hard-coded.

Use ng-switch on directive where you can compare the type and create elements based on the condition match. For example:

<div class="form-group" ng-repeat="elem in formElements">
 <div class="col-lg-12" ng-switch on="elem.eleType">
  <input ng-switch-when="text" type="text" id="{{elem.id}}" name="{{elem.id}}" class="{{elem.class}}" placeholder="{{elem.placeholder}}" popover-trigger="focus" popover="{{elem.popoverText}}">
  <input ng-switch-when="password" type="password" id="{{elem.id}}" name="{{elem.id}}" class="{{elem.class}}" placeholder="{{elem.placeholder}}" popover-trigger="focus"  popover="{{elem.popoverText}}">
  <input ng-switch-when="email" type="email" id="{{elem.id}}" name="{{elem.id}}" class="{{elem.class}}" placeholder="{{elem.placeholder}}" popover-trigger="focus"  popover="{{elem.popoverText}}">
 </div>
</div>

In this example you are instructing angular script to compare elem.eleType using ng-switch on in second div against actual type i.e, text, password and email in the input tag (compared using ng-switch-when, and only that input element is create where the condition matches, rest will be ignored.

like image 42
Chandre Gowda Avatar answered Oct 22 '22 12:10

Chandre Gowda


<input type="text" ng-model="myModel" ng-if="inputType === 'text'"/>
<input type="password" ng-model="myModel" ng-if="inputType === 'password'"/>

This works for me.

like image 3
George I. Avatar answered Oct 22 '22 12:10

George I.


Here is a slight extension to @vidriduch's answer. In this case I am using a model object 'config' of the form {type:"password", value:"topsecret"}, and displaying it like this:

<input type="{{config.type}}" ng-model="config.value">

Ideally I could change the config object as required, and use the same input element to edit any config record with matching type/value. My original way of switching records was to call the below scope function:

$scope.newRecord = function (newcfg) {
    $scope.config = newcfg;
};

However, I sometimes got conversion errors or complaints about validation. This is in Chrome 47. It really didn't like switching from text to dates, for example. The browser seemed to pick up the change of value before the change in type, or vv.

I solved this by forcing the model (and so the type) to reset in between changes.

$scope.newRecord = function (newcfg) {
   $scope.config = {}; //clear the model object
   $timeout(function() {
      $scope.config = newcfg;
   }, 0); //zero delay needed

};

This may not be an ideal solution, but it illustrates a 'gotcha' that others might experience.

like image 1
Trevedhek Avatar answered Oct 22 '22 11:10

Trevedhek