0

I have a problem where by a form within my ng-controller doesnt seem to change the properties in the controller that I thought it would. After some reading around it seems I wasn't fully aware of prototypal inheritance, but thanks to the internet and SO I updated my code as such. But unfortunately its still not working and I cannot figure out why.

Here is my HTML

<div ng-app="licenceApp" ng-controller="licenceController"> 
 <div class="hover panel" ng-class="{switch : licenceFormVisible}">
 <div class="highlightedSection nosidepad clearfix back"> 
 <div class="highlightedSubSection" ng-class="{fullsize : uploadModel.active}" ng-show="!Applying && !FinishedWithErrors && !offlineActivationScreenVisible">
 <h2>Licence File</h2>
 Upload and apply a valid licence file{{uploadModel.active}}<br /><br />
 ...
 <form id="hiddenUploadForm" name="hiddenUploadForm" target="hiddenUploadFormFileTarget" action="/settings/uploadILP" method="post" enctype="multipart/form-data" style="display: none;">
 <input id="hiddenUploadFormFile" name="file" type="file" ng-model="uploadModel.uploadFileName" onchange="angular.element(this).scope().uploadFileChanged()" />
 <iframe id="hiddenUploadFormFileTarget" name="hiddenUploadFormFileTarget" iframe-onload="uploadFileFinished()"></iframe>
 </form>
 </div>
 </div>
 </div>

ViewModel

angular.module('licenceApp.controllers', [])
 .controller('licenceController', ['$scope', 'licenceAPIservice', '$filter', '$timeout', function ($scope, licenceAPIservice, $filter, $timeout) {
 $scope.uploadModel = {
 active: false,
 uploadFileName: "",
 uploading: false
 };
 $scope.uploadFileChanged = function () {
 $scope.uploadModel.active = true;
 $scope.uploadModel.uploading = true;
 $('#hiddenUploadForm').submit();
 }
 ...

So when I change uploadModel.active in a function it shows the correct value through a console.log but the display doesnt mimic the new value! Am I still subject to prototypal inheritance here? Note that uploadFileChanged is hit when the input file control is changed.

asked Nov 18, 2014 at 8:58

1 Answer 1

1

onchange is a javascript event outside angular so you would need to call $apply to notify angular of the changes in the scope. Fortunately there is a angular directive that does that for you (ng-change).

<input id="hiddenUploadFormFile" 
 name="file" type="file" 
 ng-model="uploadModel.uploadFileName"
 ng-change="uploadFileChanged()" />

EDIT:

ngModel doesn't work with input type=file (issue), hence ngChange won't work as it required ngModel to work.

The right way to approach it then would be to call $apply inside you uploadFileChanged function.

HTML:

<input id="hiddenUploadFormFile" 
 name="file" type="file" 
 onchange="angular.element(this).scope().uploadFileChanged()"/>

JS:

 $scope.uploadFileChanged = function () {
 $scope.$apply(function() {
 $scope.uploadModel.active = true;
 $scope.uploadModel.uploading = true;
 $('#hiddenUploadForm').submit();
 });
 }

If you plan to use input type file, it might be work to create a simple directive that handles the change event without the need to access the element scope that way.

answered Nov 18, 2014 at 9:07
Sign up to request clarification or add additional context in comments.

7 Comments

Yes I just double checked and it doesnt work with inputs.. In this case do I just need to use $apply within my function?
ngChange only requires ngModel to work, so if the input field has ngModel it should work fine.
Thanks. If I add that code I get an error on the apply line which is: Uncaught TypeError: undefined is not a function
It was $apply :D - ok so thats great and it works, thankyou. But can I ask why? Why do I need to apply when in other functions I dont? It must have found the scope as the function was executed?
Because of the way two-way data binding works, when you change a property in $scope that a it's being used in your template angular needs to be informed when that property change in some way and the way that it uses is called $digest which is a recursive function that travels accross all scopes checking for equality checks in the fields that it's supposed to keep in sync with the template.
|

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.