Selecting another HTML element from an ng-click attribute - javascript

I am attempting to pass a file into a function, where the file is originated from an input type of file. My code looks something like this.
<input type="file" id="scvFileUploadId"/>
<button id="uploadFilesubmit" ng-click"ctrl.uploadFile()">Upload</button>
In short, I would like to take the file that has been added to the input and pass it into the parameter of the function of the ng-click attribute that is fired when the button is clicked. I think this may be simple, but I cannot wrap my head around it at the moment.
I'm trying to do something like this.
<input type="file" id="scvFileUploadId"/>
<button id="uploadFilesubmit" ng-click"ctrl.uploadFile(#scvFileUploadId.file)">Upload</button>

My solution was to use Angular's element selector to point to the input element holding the file, and then pass the result of that as the parameter into the function, like so:
<input type="file" id="scvFileUploadId" />
<button id="uploadFilesubmit" onclick="angular.element(this).controller().uploadFile(angular.element(document.querySelector('#csvFileUploadID'))[0].files[0])">Upload</button>
I'm not sure if this solution is the most 'Angular' way of doing it, but there were existing workarounds for some lack of support with Angular input file uploading being done on this part of the application that forced me to interact with DOM, so this does suffice in my scenario.

I highly recommend using existing directives created by the community;
https://github.com/nervgh/angular-file-upload
https://github.com/danialfarid/ng-file-upload
But if you are restricted and want to avoid 3rd parties you can see this implementation:
ng-model for <input type="file"/>
<input type="file" fileread="vm.uploadme" />
<button id="uploadFilesubmit" ng-click"ctrl.uploadFile(vm.uploadme)">Upload</button>

You can use a simple directive with NgModelController to add ngModel support for the input type='file' like:
angular.module('myApp', [])
.controller('TestUploadController', ['$scope', function ($scope) {
var ctrl = this;
ctrl.imageFile = null;
ctrl.clearFile = clearFile;
ctrl.uploadFile = uploadFile;
function clearFile() {
ctrl.imageFile = null;
}
function uploadFile(file) {
if (file) {
console.log('Upload: ', file);
}
}
}])
.directive('fileUpload', [function () {
return {
require: "ngModel",
restrict: 'A',
link: function ($scope, el, attrs, ngModel) {
function onChange (event) {
//update bindings with $applyAsync
$scope.$applyAsync(function(){
ngModel.$setViewValue(event.target.files[0]);
});
}
//change event handler
el.on('change', onChange);
//set up a $watch for the ngModel.$viewValue
$scope.$watch(function () {
return ngModel.$viewValue;
}, function (value) {
//clear input value if model was cleared
if (!value) {
el.val("");
}
});
//remove change event handler on $destroy
$scope.$on('$destroy', function(){
el.off('change', onChange);
});
}
};
}]);
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.angularjs.org/1.6.2/angular.js"></script>
<div ng-app="myApp">
<div ng-controller="TestUploadController as $ctrl">
<input type="file" file-upload ng-model="$ctrl.imageFile" />
<input type="button" ng-click="$ctrl.uploadFile($ctrl.imageFile)" value="Upload" />
<input type="button" ng-click="$ctrl.clearFile()" value="Reset" />
<div ng-if="$ctrl.imageFile">
{{$ctrl.imageFile.name}}<br />
{{$ctrl.imageFile.size}} byte(s)<br/>
{{$ctrl.imageFile.type}}
</div>
</div>
</div>

Related

How to submit angular js form using ng-click?

I want to provide id and date though the html form and then submit these values
to the js controller and execute one of my endpoint with that values (adminId and adminDate). I think something is missing.
// adminForm.html
<form class="form-horizontal" role="form" ng-controller="AdminController">
<input class="form-control" id="adminId" placeholder="adminId" ng-model="formInfo">
<input class="form-control" id="adminDate" placeholder="adminDate" ng-model="formInfo">
<button type="submit" ng-click="adminUpload()" class="btn btn-success">AdminUpload</button>
</form>
// AdminController.js
define([], function() {
function AdminController($scope, $http) {
$scope.adminUpload = function() {
$http.get('/app/endpoint/$scope.adminId/$scope.adminDate').success(
function () {
alert("Something went wrong!");
}
).error(
function () {
alert("Everything fine!");
}
);
};
}
AdminController.$inject = ['$scope', '$http'];
return AdminController;
}
);
There are a few errors in your code, the template, and the controller. I'll list them one by one to explain and provide one example,
The live example
https://plnkr.co/edit/G3f6X0mUVwQ4Nxj2
The Explanation
In Template:
Your ng-model in both inputs are referencing the same model. You should make reference to different elements (or different attributes of the same element). So, I used other elements for the sake of the example.
Your button is type=submit. It's a problem because the submit default behavior is POST the form information (and load the form's action). So, I redefined the button just as a button.
In Controller:
You're not interpolating the string on the request of the URL. You're always fetching '/app/endpoint/$scope.adminId/$scope.adminDate'. You should be fetching '/app/endpoint/(value of $scope.adminId)/( value of $scope.adminDate)'.So I used a template literal (The strings with the back quote symbol)and concatenate the strings with the variable values.
You were using success/error functions in the inverse order. Your success says "Something went wrong!" and your error says "Everything fine!"
Based on AngularJS documentation (https://docs.angularjs.org/api/ng/service/$http), there are no success/error functions after $http.get, so even when they were so used and they were part of AngularJS maybe they aren't in your version. So, my recommendation would be to use the recommendation function which is then(successCallback, errorCallback)
After all this explanation the code would be
template
<form class="form-horizontal" role="form">
<input
class="form-control"
id="adminId"
placeholder="adminId"
ng-model="adminId"
/>
<input
class="form-control"
id="adminDate"
placeholder="adminDate"
ng-model="adminDate"
/>
<button type="button" ng-click="adminUpload()" class="btn btn-success">
AdminUpload
</button>
</form>
controller
$scope.adminUpload = function () {
const url = `/app/endpoint/${$scope.adminId}/${$scope.adminDate}`;
alert(url);
$http
.get(url)
.then(function () {
alert('Everything fine!');
}, function () {
alert('Something went wrong!');
});
};

Get the new value from an input with AngularJS

I am trying to convert a JQuery website to AngularJS, but I can't figure this one out.
In JQuery I used:
$('.bet').change(function(e) {
// Do someting
};
I tried to do multiple things with AngularJS but no success.
At the moment I have this in my HTML and I have nothing related in my Angular file
index.php
<input type="number" class="form-control" id="bet" name="bet" placeholder="Your bet" ng-model="bet" ng-change="bet( {{bet}} )"/>
How to do this in AngularJS?
From the documentation:
Evaluate the given expression when the user changes the input. The expression is evaluated immediately, unlike the JavaScript onchange event which only triggers at the end of a change (usually, when the user leaves the form element or presses the return key).
So basically you need to bind a function to a ng-change attribute, like this way:
<input type="number" name="bet" placeholder="Your bet" ng-model="bet" ng-change="betChanged(bet)"/>
and the listener in your controller:
$scope.betChanged = function(bet){
//do something...
console.log(bet);
}
Like this, betChanged will be called every time bet will change, much like the native javascript input function.
var myApp = angular.module('myApp',[]);
myApp.controller('myCtrl', ['$scope', function($scope) {
$scope.bet = "";
$scope.onBetChanged = function () {
alert($scope.bet);
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<input type="number" class="form-control" id="bet" name="bet" placeholder="Your bet" ng-model="bet" ng-change="onBetChanged()"/>
</div>
what about $watch
<div ng-app="myApp" ng-controller="myCtrl">
First Name:
<input type="text" ng-model="firstName"><br>
Full Name: {{firstName }}
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope, $window) {
$scope.$watch('firstName', function (newValue, oldValue) {
console.log('oldValue=' + oldValue);
console.log('newValue=' + newValue);
//do something
$window.alert("Event fired");
});
});
</script>

How to apply ng-focus and ng-change on same input field?

Trying to call a function A when user focuses on input field using ng-focus event, and to call function B when the user starts writing and want to capture this event using ng-change event.
<input type="text" ng-focus="functionA()" ng-change="functionB()">
What is the problem with this? Seems to be working fine for me. The only thing I see a problem is that you haven't added ng-model. It is required for the ng-change to work.
var app = angular.module("sa", []);
app.controller("FooController", function($scope) {
$scope.functionA = function() {
console.log("Input is focused");
};
$scope.functionB = function() {
console.log("changing");
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app="sa" ng-controller="FooController">
<input type="text" ng-focus="functionA()" ng-change="functionB()" ng-model="myValue" />
</div>

How do I reset a form in angularjs?

See Fiddle: http://jsfiddle.net/hejado/7bqjqc2w/
I'm trying to form.reset() my form using angular.
HTML:
<div ng-controller="formCtrl">
<form name="resetme" id="resetme">
<input ng-model="text" type="text" />
<input file-model="file" type="file" />
<button type="button" ng-click="resetForm()">reset</button>
</form>
</div>
JS:
.controller('formCtrl', function($scope) {
$scope.resetForm = function() {
//$scope.resetme.reset();
document.getElementById('resetme').reset();
};
});
Please note: I'm using this kind of form to ajax-upload a file. The page is not refreshing and I don't want to use any reset-buttons. (I'm using one in the fiddle for simplicity.) I want to call the reset-function after the fileupload is finished (via http success).
I'm using
<input type="file" />
so I can't reassign empty values to all my inputs, because file inputs are readonly.
Calling the reset() function on the DOM element works, but I was told talking to the DOM in angular would be evil, so...
I'd like to know, how this would be done the angular way. I tried naming the form and referencing it via $scope.formname but I'm not able to call Web API functions... (commented line)
How can I achieve this?
UPDATE
After reading some of the answers, I should make clear, that I am using ngModel and a custom directive fileModel to get a hold of the file-object.
Some of the solutions worked in resetting the value of the input field, but the model is not cleared (neither file, nor text). Custom directives are the answer to that, but this kinda exceeds the scope of this question.
I wrote about this topic a couple years ago. I don't know if the Angular team has yet implemented a native form reset directive but you can do so yourself. There are a couple caveats to this implementation: it only works for one model (if you need to support more see the followup post) and the issue of when to initialize the original values. Also, I never tested this with file inputs so I am not sure it would work with those.
There was an issue for this but it was closed due to inactivity. :/
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', ['$scope',
function($scope) {
$scope.myModel = {
foo: 'Boop',
bar: 'Beep'
};
$scope.myModelCopy = angular.copy($scope.myModel);
}
]);
myApp.directive('resetDirective', ['$parse',
function($parse) {
return function(scope, element, attr) {
var fn = $parse(attr.resetDirective);
var masterModel = angular.copy(fn(scope));
// Error check to see if expression returned a model
if (!fn.assign) {
throw Error('Expression is required to be a model: ' + attr.resetDirective);
}
element.bind('reset', function(event) {
scope.$apply(function() {
fn.assign(scope, angular.copy(masterModel));
scope.form.$setPristine();
});
// TODO: memoize prevention method
if (event.preventDefault) {
return event.preventDefault();
} else {
return false;
}
});
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="MyCtrl">
<form reset-directive="myModel" name="form">
<input type="text" ng-model="myModel.foo" />
<input type="text" ng-model="myModel.bar" />
<input type="reset" value="Reset" />
<pre>myModel: {{ myModel | json }}</pre>
<pre>myModelCopy: {{ myModelCopy | json }}</pre>
<pre>form pristine: {{ form.$pristine }}</pre>
</form>
</div>
</body>
You can try :
reset
$scope.resetForm = function(form) {
//Even when you use form = {} it does not work
form.fieldA = null;
form.fieldB = null;
///more fields
}
Or
$scope.resetForm = function(form) {
//Even when you use form = {} it does not work
angular.copy({},form);
}
See Demo
You'd want to attach ng-model to each of your input fields then null them out via $scope. Either that or make a custom directive
I've just had a similar problem with forms not resetting. Here's what I would do:
In your resetform() function, I would include statements that set both of your ng-models in your input to "". For example:
**HTML**
<input ng-model="text" type="text" />
<input file-model="file" type="file" />
**JS**
.controller('formCtrl', function($scope) {
$scope.resetForm = function() {
$scope.text = "";
$scope.file = null;
};
});
Not certain if this will work for file-models but I'm certain it will remove the text. Best of luck!
If you don't want to use ng-model and proper reset type of button you can use this code, however this is not proper angular way to reset the form but it will work
$scope.reset = function(){
$('form').children('*').each(function(){
$(this).val('');
});
}
Here's the Plunker
To reset the form data use following code :
$scope.resetEmployeeData = function() {
$scope.employeeCred.userName = '';
$scope.employeeCred.employeeNo = '';
$scope.employeeCred.sapNo = '';
$scope.employeeCred.emailD = '';
$scope.employeeCred.mobileNo = '';
**this**.createEmployee.$setPristine();
**this**.createEmployee.$setUntouched();
};
use this rather than $scope.

Angularjs when typing in input is paused

I am using jQuery to figure out when an input has started typing and then paused.
var timeoutId;
$('#container').on('input propertychange change', 'form', function(e) {
clearTimeout(timeoutId);
timeoutId = setTimeout(function() {
console.log("paused");
}, 3000);
});
I'm trying to find an appropriate Angularjs solution to accomplish this task.
I'm thinking I need to use ng-change or something similar to my input areas. I'm new to Angular.
Found out the answer. You would do this where 3000 is the amount of milliseconds you want to wait.
<input ng-change="functionToRun()" ng-model-options="{debounce: 3000}" />
Edit: #bryan has the correct answer!
You can use the ng-change directive on your inputs and the $timeout service to handle your pause event.
Working plunker:
http://plnkr.co/edit/Y6NtjabxeGaQpOIif1U3?p=preview
<body ng-app="inputExample">
<script>
angular.module('inputExample', [])
.controller('ExampleController', ['$timeout', '$scope', function($timeout, $scope) {
$scope.checkPause = function() {
$timeout.cancel($scope.pause);
$scope.pause = $timeout(function() {
alert("pause");
}, 1000);
};
}]);
</script>
<div ng-controller="ExampleController">
<form name="myForm">
<label>
User name:
<input ng-change="checkPause()" type="text" name="userName" ng-model="user.name" required>
</label>
</form>
</div>
</body>

Categories

Resources