ng-change on <input type="file" - javascript

I am trying to run my upload() function when a file input changes. However, I can't make it work.
HTML:
<input type="file" ng-model="image" ng-change="uploadImage()">
JS:
$scope.uploadImage = function() {
console.log('Changed');
}
What am I doing wrong?

Try this out:- http://jsfiddle.net/adiioo7/fA968/
JS:-
function myCtrl($scope) {
$scope.uploadImage = function () {
console.log("Changed");
}
}
HTML:-
<div ng-app ng-controller="myCtrl">
<input type="file" ng-model="image" onchange="angular.element(this).scope().uploadImage()" />
</div>

Here's a directive I made that accomplishes what you are asking. If I'm not mistaken, I think the other solutions won't work in production mode, but this one does. It is used like so:
<input ng-upload-change="fileChanged($event)" />
In your controller:
$scope.fileChanged = function($event){
var files = $event.target.files;
}
And for the directive to include somewhere in your code:
angular.module("YOUR_APP_NAME").directive("ngUploadChange",function(){
return{
scope:{
ngUploadChange:"&"
},
link:function($scope, $element, $attrs){
$element.on("change",function(event){
$scope.$apply(function(){
$scope.ngUploadChange({$event: event})
})
})
$scope.$on("$destroy",function(){
$element.off();
});
}
}
});
This code is released into the public domain, no attributions required.
You should also be aware that if somebody selects a file, closes the file input, and then selects the same file again later on, it won't fire the change function again. To fix this, I've created a more complete directive that replaces the input under the hood each time you use it. I put it on github here:
https://github.com/dtruel/angular-file-input/tree/master

Another interesting way to listen to file input change is with a watch over the ng-model attribute of the input file.
Like this:
HTML -> <input type="file" file-model="change.fnEvidence">
JS Code ->
$scope.$watch('change.fnEvidence', function() {
alert("has changed");
});
Hope this helps.

Use ng-file-select="upload($files)"
'<input type="file" class="form-control" ng-model="alunos.file" accept="image/*" ng-file-select="upload($files)"/>'
where upload is a function:$scope.upload = function(file){
console.log(file);
};

Related

ng-model is not updating its value if I reselect modal to add name again, not able to bind ng-model with controller after another filename is injected

I have upload file feature and writing the filename inside input box, but when I upload file next time, the ng-model inside input won't update the filename as newer.How to update ng-model everytime I select new file. Here is the code.
JS:
$scope.setFile = function(element) {
$scope.$apply(function($scope) {
$scope.myFile = element.files[0];
$scope.FileName=$scope.myFile.name;
$scope.FileName = $scope.FileName.replace(/\..+$/, '');
$scope.fileExtension = element.files[0].name.split('.').pop();
console.log($scope.FileName);
console.log($scope.fileExtension);
});
};
HTML code:
<input type="file" name="upload" ng-model="diagram" onchange="angular.element(this).scope().setFile(this)" base-sixty-four-input>
<p>Tags:</p>
<p><input type="text" class="form-control input-sm" ng-model="FileName" ></p>
Any help is appreciated. Thanks
Can you please try this?? No need to pass $scope to apply.
$scope.setFile = function(element) {
$scope.$apply(function() {
$scope.myFile = element.files[0];
$scope.FileName=$scope.myFile.name;
$scope.FileName = $scope.FileName.replace(/\..+$/, '');
$scope.fileExtension = element.files[0].name.split('.').pop();
console.log($scope.FileName);
console.log($scope.fileExtension);
});
};
Don't use $scope.apply, but use the safer $timeout service:
$scope.setFile = function(element) {
$timeout(function(){
$scope.myFile = element.files[0];
$scope.FileName=$scope.myFile.name;
$scope.FileName = $scope.FileName.replace(/\..+$/, '');
$scope.fileExtension = element.files[0].name.split('.').pop();
console.log($scope.FileName);
console.log($scope.fileExtension);
}, 0);
};
This way, your bindings will be always up-to date with your events (and thus, your $scope.variable will be assigned).
If this does not fix your problem, you may have a problem with scopes and/or your variable is misassigned elsewhere.

Angular few events on one button

learning Angular, met another issue in my way, hope anyone can help.
I've got one button that must perform two actions: download something and send formdata to the server. So I've wrote this:
<form id='download'>
<label for='name'>Name:</label>
<input type='name' ng-model='nameValue'>
<label for='email'>Email:</label>
<input type='email' id='email' ng-model='emailValue'>
</form>
<a ng-click='sendFormDataIfVal()' href="{{filename}}" download="{{filename}}">Download</a>
But the problem and my question is - now downloading and sending occur simultaneously while I wanna download file only if emailValue pass validation and nameValue is not empty. Suppose it's gonna be something like this, but I dunno how to complete function
$scope.sendFormDataIfVal = function() {
$scope.validateEmail() && $scope.sendFormData(); // download & send
if(!$scope.validateEmail()) {
// do not download and do not send
}
};
Any advise will be greatly... u know :)
One approach is to disable the link using css.
once enabled, both the click event handler and the native download function will work.
toggle the link's 'disabled' css class via a validation function
here is a working example
HTML
<body ng-app="myApp" ng-controller="myController">
<form id="download">
<label for="name">Name:</label>
<input type="name" ng-model="nameValue" />
<label for="email">Email:</label>
<input type="email" id="email" ng-model="emailValue" />
</form>
<a ng-class="{'disabled' : !isFormValid()}" ng-click="sendFormData()" ng-href="{{fileUrl}}" download="{{fileName}}" >Download</a>
</body>
JS
var myApp = angular.module('myApp',[]);
myApp.controller('myController', ['$scope', function($scope) {
$scope.emailValue = 'sample#email.com';
$scope.nameValue = "";
$scope.fileUrl = "http://thatfunnyblog.com/wp-content/uploads/2014/03/funny-videos-funny-cats-funny-ca.jpg";
$scope.fileName = "funny-cat.jpeg";
$scope.isEmailValid = function(){
//replace this simplified dummy code with actual validation
return $scope.emailValue.indexOf('#') !== -1;
}
$scope.isFormValid = function(){
return $scope.isEmailValid() && $scope.nameValue.length;
}
$scope.sendFormData = function(){
console.log('sent that data');
}
}]);
CSS
a.disabled{
/*simulate disabled using css, since this property is nto supported on anchor element*/
color:gray;
pointer-events:none;
}
Try this:
$scope.sendFormDataIfVal = function() {
if(!$scope.validateEmail()) {
// do not download and do not send
}
else{
download and send
}
};

Angular.js : How to bind "change" event to service

First of all, I'm new to angular.js...
I have a HTML5 page where I can add new URLs with a name. Now, I want to have a check to a back-end service to check if the URL already exist. How can I bind the “onChange” event on the input boxes to a service function?
I have tried to find the solution, but I have not been able to find anything that describes this easily.
<div ng-controller="newLink">
<input class="url" value="{{Url}}" ng-model="Url" placeholder="Please type a URL"/>
<input class="name" value="{{Name}}" ng-model="Name" placeholder="Type a name" />
<div class="status"></div>
</div>
<script>
app.controller('newLink', ['$scope', 'appService', function ($scope, appService) {
$scope.Name = '';
$scope.Url = '';
}]);
</script>
You can use the ngChange directive
<input ng-change="onChange()">
// in controller
$scope.onChange = function(){
// call your service function here
}
For further information, see: http://docs.angularjs.org/api/ng/directive/ngChange
Two simple solutions to this problem:
use ng-change directive:
<input ng-change="doSomething()">
$scope.doSomething = function() {};
$watch value change
<input ng-model="Url">
$scope.$watch('Url', function() {});

AngularJS does not send hidden field value

For a specific use case I have to submit a single form the "old way". Means, I use a form with action="". The response is streamed, so I am not reloading the page. I am completely aware that a typical AngularJS app would not submit a form that way, but so far I have no other choice.
That said, i tried to populate some hidden fields from Angular:
<input type="hidden" name="someData" ng-model="data" /> {{data}}
Please note, the correct value in data is shown.
The form looks like a standard form:
<form id="aaa" name="aaa" action="/reports/aaa.html" method="post">
...
<input type="submit" value="Export" />
</form>
If I hit submit, no value is sent to the server. If I change the input field to type "text" it works as expected. My assumption is the hidden field is not really populated, while the text field actually is shown due two-way-binding.
Any ideas how I can submit a hidden field populated by AngularJS?
You cannot use double binding with hidden field.
The solution is to use brackets :
<input type="hidden" name="someData" value="{{data}}" /> {{data}}
EDIT : See this thread on github : https://github.com/angular/angular.js/pull/2574
EDIT:
Since Angular 1.2, you can use 'ng-value' directive to bind an expression to the value attribute of input. This directive should be used with input radio or checkbox but works well with hidden input.
Here is the solution using ng-value:
<input type="hidden" name="someData" ng-value="data" />
Here is a fiddle using ng-value with an hidden input: http://jsfiddle.net/6SD9N
You can always use a type=text and display:none; since Angular ignores hidden elements. As OP says, normally you wouldn't do this, but this seems like a special case.
<input type="text" name="someData" ng-model="data" style="display: none;"/>
In the controller:
$scope.entityId = $routeParams.entityId;
In the view:
<input type="hidden" name="entityId" ng-model="entity.entityId" ng-init="entity.entityId = entityId" />
I've found a nice solution written by Mike on sapiensworks. It is as simple as using a directive that watches for changes on your model:
.directive('ngUpdateHidden',function() {
return function(scope, el, attr) {
var model = attr['ngModel'];
scope.$watch(model, function(nv) {
el.val(nv);
});
};
})
and then bind your input:
<input type="hidden" name="item.Name" ng-model="item.Name" ng-update-hidden />
But the solution provided by tymeJV could be better as input hidden doesn't fire change event in javascript as yycorman told on this post, so when changing the value through a jQuery plugin will still work.
Edit
I've changed the directive to apply the a new value back to the model when change event is triggered, so it will work as an input text.
.directive('ngUpdateHidden', function () {
return {
restrict: 'AE', //attribute or element
scope: {},
replace: true,
require: 'ngModel',
link: function ($scope, elem, attr, ngModel) {
$scope.$watch(ngModel, function (nv) {
elem.val(nv);
});
elem.change(function () { //bind the change event to hidden input
$scope.$apply(function () {
ngModel.$setViewValue( elem.val());
});
});
}
};
})
so when you trigger $("#yourInputHidden").trigger('change') event with jQuery, it will update the binded model as well.
Found a strange behaviour about this hidden value () and we can't make it to work.
After playing around we found the best way is just defined the value in controller itself after the form scope.
.controller('AddController', [$scope, $http, $state, $stateParams, function($scope, $http, $state, $stateParams) {
$scope.routineForm = {};
$scope.routineForm.hiddenfield1 = "whatever_value_you_pass_on";
$scope.sendData = function {
// JSON http post action to API
}
}])
I achieved this via -
<p style="display:none">{{user.role="store_user"}}</p>
update #tymeJV 's answer
eg:
<div style="display: none">
<input type="text" name='price' ng-model="price" ng-init="price = <%= #product.price.to_s %>" >
</div>
I had facing the same problem,
I really need to send a key from my jsp to java script,
It spend around 4h or more of my day to solve it.
I include this tag on my JavaScript/JSP:
$scope.sucessMessage = function (){
var message = ($scope.messages.sucess).format($scope.portfolio.name,$scope.portfolio.id);
$scope.inforMessage = message;
alert(message);
}
String.prototype.format = function() {
var formatted = this;
for( var arg in arguments ) {
formatted = formatted.replace("{" + arg + "}", arguments[arg]);
}
return formatted;
};
<!-- Messages definition -->
<input type="hidden" name="sucess" ng-init="messages.sucess='<fmt:message key='portfolio.create.sucessMessage' />'" >
<!-- Message showed affter insert -->
<div class="alert alert-info" ng-show="(inforMessage.length > 0)">
{{inforMessage}}
</div>
<!-- properties
portfolio.create.sucessMessage=Portf\u00f3lio {0} criado com sucesso! ID={1}. -->
The result was:
Portfólio 1 criado com sucesso! ID=3.
Best Regards
Just in case someone still struggles with this, I had similar problem when trying to keep track of user session/userid on multipage form
Ive fixed that by adding
.when("/q2/:uid" in the routing:
.when("/q2/:uid", {
templateUrl: "partials/q2.html",
controller: 'formController',
paramExample: uid
})
And added this as a hidden field to pass params between webform pages
<< input type="hidden" required ng-model="formData.userid" ng-init="formData.userid=uid" />
Im new to Angular so not sure its the best possible solution but it seems to work ok for me now
Directly assign the value to model in data-ng-value attribute.
Since Angular interpreter doesn't recognize hidden fields as part of ngModel.
<input type="hidden" name="pfuserid" data-ng-value="newPortfolio.UserId = data.Id"/>
I use a classical javascript to set value to hidden input
$scope.SetPersonValue = function (PersonValue)
{
document.getElementById('TypeOfPerson').value = PersonValue;
if (PersonValue != 'person')
{
document.getElementById('Discount').checked = false;
$scope.isCollapsed = true;
}
else
{
$scope.isCollapsed = false;
}
}
Below Code will work for this IFF it in the same order as its mentionened
make sure you order is type then name, ng-model ng-init, value. thats It.
Here I would like to share my working code :
<input type="text" name="someData" ng-model="data" ng-init="data=2" style="display: none;"/>
OR
<input type="hidden" name="someData" ng-model="data" ng-init="data=2"/>
OR
<input type="hidden" name="someData" ng-init="data=2"/>

How to clear a text field?

I want to place a cross button next to a text field, which, on clicking it, clears the value entered by the user. In other words, it empties the field. Please help..
And I also want to focus the field, but after some 2 or 3 seconds..
Like this:
$('#myButton').click( function () {
$('#myField').val('');
});
Or without jQuery
document.getElementById('myButton').onclick = function () {
document.getElementById('myField').value = '';
});
Try this,
$('#button').click(function(){
$('#inputBox').val('');
});
Have you tried anything at all? But this should do (edit after misread, see below):
$('#your_button').click(function() { $('#your_textbox').val(''); });
In Javascript:
document.getElementById('textField1').value = "";
Well, learn to break your tasks into smaller one and everything will become much easier. Here, for example, you have 2 tasks:
1) Place a "X" button near input. This is achieved by CSS and HTML. You HTML might look like:
Then you should align your image with you input
2) Actual erasing. In jQuery:
$("#x_button").click( function() {
$("#input_id").val( "" );
});
But this is real basics of web development, so you should really consider to read some kind of book on it.
You can do it with html5 value.
<input type="text" placeholder="Your text here">
Assuming your text field looks like this one :
<input type="text" id="myText"></input>
and your button looks like this one :
<input type="button" id="myButton"></input>
You just have to do this in javascript :
<script type="text/javascript">
var myButton = document.getElementById('myButton');
myButton.addEventListener("click", function () {
document.getElementById('myText').value = '';
}, false);
</script>
If you're using jQuery it's even easier :
<script type="text/javascript">
$('#myButton').click(function() {
$('#myText').val('');
});
</script>
here is a sample:
Html:
<input type="text" id="txtText" value="test value" />
<input type="button" id="btnClear" value="Clear" />
javascript:
$(document).ready(function () {
$("#btnClear").click(ClearText);
});
function ClearText() {
$("#txtText").val("");
}

Categories