Dynamically change an input field's placeholder? - javascript

I am working with Javascript and the d3 library, and AngularJS.
Is there a way to dynamically change an input box's placeholder? I am working with a calendar widget and multiple views and wanted to see if there was a way to have the placeholder always be the value that was last inputted into the field.
I wrote a small function that always returns the last thing that was entered into the input field...but then when I tried setting placeholder=functionIwrote() it literally makes the placeholder "fucntionIwrote()" instead of running the function.

I can't comment but... If you're using angularJs, you just have to bind the model of your input to the placeholder!
<input type="date" placeholder="myModel" ng-model="myModel" />
This way, your input would always be the latest filled value.
If you want to change your view, and then retrieve datas, then you have to store them outside of the controller scope - which is "cleaned" every time if you're using the ngIf directive -.
A good way to do this is to use a service as persistance layer.

Since you want the placeholder to be changed or updated both automatically and dynamically, you may use the jQuery code below:
$(function() {
$('input').on('change blur', function() {
!this.value || $(this).attr('placeholder', this.value);
});
});
WORKING JS FIDDLE DEMO

Yes you can do it in this way ,
<input
placeholder="Select Date"
onfocus="(this.type='date')"
onblur="if (!this.value) this.type = 'text'">

here's a fiddle: http://jsfiddle.net/bBh3L/
'placeholder' is an element attribute, so you can use $('#myInput').attr(attributeName, attributeValue) to set it.
In this case, I mapped the button click to change the placeholder using:
$('#myInput').attr('placeholder', 'new one');

I guess that you're trying to wrap your calendar widget into an angular directive, if so, here's what I did for a similar use case (I display the accepted/valid format as placeholder):
module.directive('yourDirective', [function() {
return {
link: function($scope, $element, $attrs, $controller) {
// bind 'yourValue' (the one you want to show as placeholder) in the scope
$scope.$watch('yourValue', function(value) {
$attrs.$set('placeholder', value);
});
}
};
}]);

There exists a conditional attribute property in AngularJS ng-attr-{property_name}
For example, I'm using different placeholders for different search options using
ng-attr-placeholder="{{isAdvanceSearch ? setPlaceholder(searchOption) : 'John Smith, 08/23/1970, 123'}}"
Here on the basis of isAdvanceSearch variable, I'm setting different placeholders in setPlaceholder method.
setPlaceholder method returns the placeholder to set in the input field.
$scope.setPlaceholder = function(searchOption) {
if (searchOption === "foo") {
return "Search by foo… e.g. foo1";
} else if (searchOption === "bar") {
return "Search by bar… e.g. bar123";
} else {
return "John Smith, 08/23/1970, 123";
}
};
Note: John Smith, 08/23/1970, 123 is the default placeholder.
Don't forget to wrap the expression in the {{}} brackets.

Related

Angular.js model defined in JavaScript, one property needs to be evaluated as a function

I've defined my model in the JS like so:
$scope.requirement = {
id: function() {
if($scope.dada || $scope.lala) {
return $scope.dada
}
return $scope.haha
}
}
The variables are nonsense but pretend they're defined (they are in my circumstance, this is just an example).
And then in the HTML with Angular directives I have an input like so:
<input type="text" ng-model="requirement.id" placeholder="ID">
The value returned from the function is not the value of requirement.id. How can I pass a function like above but have Angular.js evaluate the function and use the returned value?
Edit:
I tried this which didn't work:
$scope.requirement = {
id: null
}
if($scope.dada || $scope.lala) {
$scope.requirement.id = $scope.haha;
}
When I run a console.log(requirement) the value is changed however it doesn't represent the new value in the view. The input in the view still shows null
If you are doing two way binding, you need to define id as a getter/setter function that has one argument. So when a value is passed it acts as a setter, updating the model. Otherwise it just gets the current value based on your logic.
$scope.requirement = {
id: function(newId) {
if (arguments.length) {
$scope.dada = newId;
}
return ($scope.dada || $scope.lala) ? $scope.dada : $scope.haha;
}
}
You have to update your input element and add ng-model-options attribute.
<input type="text" ng-model="requirement.id" ng-model-options="{ getterSetter: true }" />
If you're just talking about one way binding, then you don't need to use the getter/setter or ng-model.
<input type="text" value="{{requirement.id()}}" readonly />
ng-model is two-way binding and the way you defined it requirement.id returns a function object (it does not execute the function), but even more, it will overwrite that object when people fill in your input field, because you told Angular to put the value of the input box into the requirement.id variable. If you only need to get the value, use {{requirement.id()}} or even more readable {{requirement.getId()}}.
If you do really need two-way binding with a function go for Daniel's solution.

how to filter input value in AngularJS

I'm trying to implement filtering on my input element.
I want to make filtering for input with type="text" field.
For instance, if the model contain more than available characters than I want to change my input value.
I've created jsfiddle
I have directive that generate html template dynamically and it contains input field.
var app = angular.module('app', [])
.controller('ctrlr', function($scope){
$scope.myModel = "test";
$scope.availableCharacters = 5;
$scope.$watch('myModel', function(newValue, oldValue){
if(!newValue){
return;
}
if(newValue.length > 5){
$scope.cutString();
}
});
$scope.cutString = function(){
var length = $scope.myModel.length;
var string = $scope.myModel.slice(0, $scope.availableCharacters);
var countStars = length - string.length;
$scope.myModel = $scope.createStars(string, countStars);
}
$scope.createStars = function(string, countStars){
for(var i = 1; i <= countStars; i++){
string = string+'*';
}
return string;
}
})
.directive('awesome' , function(){
return {
restrict:'E',
template:'<input type="text" ng-model="myModel" ng-value="myModel | filter:my" />'
}
})
Could it possibly to move my code into the filter function? I have a lot of business logic and I don't want to keep my code in the controller, because it will be reusable directive.
I think that implementing this part of functionality as a filter is not the best idea.
It would be much more dynamic if you will implement it as directive on your input element like:
<input type="text" ng-model="myModel" ng-value="myModel" max-length="20" />
In this case it would be more flexible. You will be able to pass an argument into directive (for example length of acceptable value).
Also it is not really readable for another developers to make your input as a template of your directive because of you are using model as attribute of input field and not binding it from directive.
Is there any reason why you use directive to render simple input?
If not, then just live it as input in your view and add directive instead of filter to work with data checks limitations.
Another approach is to implement custom form controls. That will allows you to control incoming and out-coming data.
Here is a example from documentation - Implementing custom form controls (using ngModel)

using angularjs $filter() inside directives

i want to hide some part of the input text value using some filter.
app.directive('limtToDate', ['$filter', function ($filter) {
var dateFormat = "DD/MM/YYYY HH:mm"
return {
restrict: 'A',
link: function (scope, ielem, attrs) {
scope.$watch(attrs.ngModel, function (v) {
console.log('value changed, new value is: ' + v);
$filter('limitTo')(ielem.val(), -5);
});
}
}}]);
http://jsfiddle.net/PqAhk/2/
well, my input text should just show 12:12 instead of 01/01/1970 12:12. and after editing the time, for example, if user change the time to 12:40 my ng-model has to be like following 1970/01/01 12:40
First, thank you all, this solution was created by #guru and many thanks to him.
http://plnkr.co/edit/VhsleIWMq8A4rJcVQDaw?p=preview
the solution takes advantage from $formatter and $parser related to the angularjs pipeline rendering.
https://docs.angularjs.org/api/ng/type/ngModel.NgModelController
ps : this solution is not compatible with angularjs.2-rc.x
If you don't want your model to change then don't use two way binding:
<div ng-app = "fiddle">
<div ng-controller="MyCtrl">
<table class="table">
<input type="text" ng-value="fromDate | limitTo:-5" />
</table>
</div>
</div>
Better yet why not make from date a real date object:
$scope.fromDate = new Date(); // current date for demonstration, set to real value
And use the date filter:
<input type="text" ng-value="fromDate | date:'HH:mm'" />
The filter in the link function -> $filter('limitTo')(ielem.val(), -5); filters the array and returns a new array with the filtered values. It has to be assigned back to the scope variable for the changes to get reflected.
Something like below.
$scope.filteredValue= $filter('limitTo')(ielem.val(), -5);
Thats intersting. Though formatting can be easy by using $formatter in the ngModelCtl syncing the input data change back to the model can be tricky.
You can use the ngModelCtl.$parsers and ngModelCtl.$formatters to set up the format and view value.
Here is a working Solution: http://plnkr.co/edit/1KqLsIwGJjwUIbs0fwmQ?p=preview

Binding text inputs to a directives attribute

I'm trying to bind a text input to an attribute within a directive, the reason being I don't want to have to introduce a controller each time I add a new directive of this type. Is this even possible or do you always have to specify a controller when using ng-model. Code example is worth a thousand words so please take a look at http://codepen.io/scottwio/pen/HKqiw . As you type in the input the amount should change.
There are two issues with your code:
scope.$watch(attrs.amount, function (v) {...}); <=>
scope.$watch('100', function (v) {...});
which is never going to change, so does not do what you want.
Since the elements attribute is never going to change, function draw(aniTime) { var amount = attrs.amount; is not so usefull.
You can fix them like this:
scope.$watch('amount', function (v) {...});
and
function draw(aniTime) {
var amount = scope.amount;
...
See, also, this short demo.
If you want to share the specified amount with the parent scope, then you need to set up a two-way data-binding and specify a property in the parent scope to bind to. E.g.:
// Parent scope
$scope.someAmount = 100;
// In HTML
<custommarc amount="someAmount" ...
// In directive
scope: {
amount: '='
...

How to select empty inputs (value="") using jQuery

How can I check for empty values of (required) input fields within a section, and then add a class to them on an event, using jQuery? So far, I have tried:
jQuery("#sender_container input.required").val("").addClass("error");
But that seems to SET the value, rather than checking it. Any ideas?
jQuery("#sender_container input.required").filter(function() {
return !this.value;
}).addClass("error");​
Why you have to use filter and not [value=""] you can see in this DEMO
The reason is: attribute selectors check the initial state of the element, not the current state. (note that you can change the "initial" state with the attr function, but it's bad practice, you should always use prop)
So if you change the input value, the current value won't effect the attribute selector. not wise... :)
Notes:
.val() returns the value of the form element, and breaks the jQuery chain,
$('selector').val().addClass('foo') Error, the return value is a string\ number
.val(valueToSet) sets the value of the form element and doesn't break the jQuery chain.
$('selector').val("some value").addClass('foo') - Valid, the returned value is a jQuery
$('input:text[value=]','#sender_container').addClass('error');
DEMO
$('#sender_container input.required[value=""]').addClass('error')
jQuery('#sender_container input.required[value=""]').addClass("error");
You can try this:
$('input:not([value!=""])').addClass('error');
DEMO
Note: This answer should not be used, and the only reason it wasn't deleted is so it can be learned from.
$field = $("#sender_container input.required");
if( ! $field.val())
{
$field.addClass("error");
}
this simple way may work.
If you only need to select based on the initial attribute value of the input then the following will do:
var elements = $('#sender_container input.required[value=""]')
But be aware that this won't work if the value attribute isn't present. It also won't work for the current input value if it has been changed by user or script.
If you'd like to get the current input value you can use jquery's filter function:
var elements = $('#sender_container input.required').filter(function() {
return this.value === '';
// alternatively for "no value":
// return !this.value;
})
After you've selected the jquery elements you can add your class:
elements.addClass('error');
to get all fields inspected this might help.
$('#sender_container [required]').each(function(index)
{
if (!($(this).val())) $(this).addClass('error');
}
});

Categories

Resources