Angular spreadsheet upload button not responding - angularjs

My application uses the Angular file upload component.
https://github.com/danialfarid/angular-file-upload
It previously worked but I seem to have broken it during refactoring, and am not sure how to fix it.
The application allows for selection of the spreadsheet, but when the Import button is pressed it just highlights but does not do anything. The onFileSelect function executes, but the submitUpload is never called. There is nothing in the debugger or console.
There is a partial which contain the spreadsheet upload component.
<div class="row">
<div class="col-md-8">
<form name="uploadForm" reset-form="resetForm" ng-submit="selector.submitUpload()" ng-controller="DesignViewCtrl" enctype="multipart/form-data">
<input type="file" name="spreadsheet" ng-file-select="onFileSelect($files)" />
</div>
<div class="col-md-2">
<input type="submit" value=" Import " class="btn btn-success" />
<p ng-show="uploaded">Success! <a ng-href="/batches/{{batchID}}">Show batch</a></p>
</form>
</div>
</div>
The relevant code in the controller:
$scope.onFileSelect = function ($files) {
return $scope.selector.file = $files[0];
};
$scope.selector.submitUpload = function () {
console.log('submit upload2');
return $scope.upload = $upload.upload({
url: '/api/batches/spreadsheet_upload.json',
file: $scope.selector.file
}).success(function (data, status, headers, config) {
console.log(JSON.stringify(data.data[0],null,' '))
$scope.selector.tabledata.push(data.data[0]);
});
};

I think the problem is a result of you having your column divs splitting the form, which results in your DesignViewCtrl not being a parent of the submit input. Try the following change in your template:
<div class="row">
<form name="uploadForm" reset-form="resetForm" ng-submit="selector.submitUpload()" ng-controller="DesignViewCtrl" enctype="multipart/form-data">
<div class="col-md-8">
<input type="file" name="spreadsheet" ng-file-select="onFileSelect($files)" />
</div>
<div class="col-md-2">
<input type="submit" value=" Import " class="btn btn-success" />
<p ng-show="uploaded">Success! <a ng-href="/batches/{{batchID}}">Show batch</a></p>
</div>
</form>
</div>
This change ensures your form element is the parent of both column divs.

Based on the documentation for angular-file-upload you don't even need to use a <form> so it seems like the library does that part for you. Try removing the form and just use a <div> for the controller, then use a <button> instead of an <input type="button"> for the Import button.
What I suspect is happening is that the ng-submit event is not being invoked when you click on your "Input button". I've experienced weird issues similar to this when using a form in angularjs and trying to rely on the form submit behavior.
Actually I just looked at it again and I think the problem really is that you have the <form> tag split over two elements (which would not be correct). If you had that rendered within the browser without a partial then it may work but I suspect that having it within the partial like and relying on AngularJS to put it in the browser won't work reliably.
So you can try one of two things:
1) Remove the form tag completely
<div class="row" ng-controller="DesignViewCtrl">
<div class="col-md-8">
<input type="file" name="spreadsheet" ng-file-select="onFileSelect($files)" />
</div>
<div class="col-md-2">
<button class="btn btn-success" ng-click="selector.submitUpload()"> Import </button>
<p ng-show="uploaded">Success! <a ng-href="/batches/{{batchID}}">Show batch</a></p>
</div>
</div>
2) Leave the form tag but make sure the syntax is valid:
<form name="uploadForm" reset-form="resetForm" ng-submit="selector.submitUpload()" ng-controller="DesignViewCtrl" enctype="multipart/form-data">
<div class="row">
<div class="col-md-8">
<input type="file" name="spreadsheet" ng-file-select="onFileSelect($files)" />
</div>
<div class="col-md-2">
<input type="submit" value=" Import " class="btn btn-success" />
<p ng-show="uploaded">Success! <a ng-href="/batches/{{batchID}}">Show batch</a></p>
</div>
</div>
</form>

Related

form.$valid is working for "required" but it's not working for ngPattern and maxlength.

If zipcode is empty then form is invalid so button is disabled but if zipcode is 2 digits error message is showing but form is showing as valid in controller. If zipcode is empty then I need to disable button but I'm checking form valid or not but dont worry about ng-disabled. I just need solution for showing the "div" if and only if form is valid.
function submitUserDetail (formValid) {
if(formValid) {
$scope.showDiv = true;
}
}
<div class="">
<div class="">
<label required>
Zip code required
</label>
<label pattern>
Invalid Zip code
</label>
</div>
<div class="">
<input type="tel" maxlength="5" class="" name="zip5"
ng-model="userDetail.zipCode" required=""
pattern="^\d{5}$"
data-validate-on-blur="true" value=""
size="5">
<span class="" title="Reset" onclick="jQuery(this).prev('input').val('').trigger('change');"></span>
</div>
</div>
<div class="">
<div class="">
<div class="">
<span class=""></span>
<button class="" href="#" id="button" ng-click="submitUserDetail(form.$valid)" ng-disabled="form.$invalid">See section</button>
<span class=""></span>
</div>
</div>
</div>
<div ng-if="showDiv">
.......
</div>
Thanks in advance.
I assume that you have a <form> wrapping the HTML provided.
If so, you should make sure your <form> tag has novalidate applied so you're using AngularJS form validation and not HTML5 form validation:
<form name="form" ng-submit="submitUserDetail(form.$valid)" novalidate>
Also, it looks like you're mixing HTML5 validation attributes with AngularJS validation attributes. You should be using ng-required and ng-pattern instead of required and pattern.

Angular validation for only 1 input field inside a form

I'm building a form using Angular 1.1.1 and Ionic.
There are many "wallets" and the user needs to send a new "value" to each of the wallet. My form has a validation for all fields which works fine when the 'submit' button for the form is pressed.
However, I also have a button next to each wallet to send only value to this wallet (not different values to all wallets). When I press it, all the validation errors appear, but I need error to be visible only for the particular wallet.
My form (index.html):
<form name="myForm" ng-submit="sendValues(wallets)" ng-controller="valuesCtrl" novalidate>
<div class="row" ng-repeat="wallet in wallets">
<div class="col item item-input-inset">
<label class="item-input-wrapper item-text-wrap">
<input name="wallet_{{wallet.id}}" type="number" ng-model="wallet.value" type="text" required/>
</label>
<span ng-show="myForm.wallet_{{wallet.id}}.$error.required">!!!</span>
</div>
<div class="col item">{{ wallet.previous }}</div>
<button ng-click="sendValue(wallet)">
<i class="ion-android-send"></i>
</button>
<span class=ng-show="myForm.$submitted==true && myForm.wallet_{{wallet.id}}.$error.required">Required</span>
</div>
<button class="button" type="submit">Submit</button>
</form>
My controller (values.js):
'Use Strict';
angular.module('App')
.controller('valuesCtrl', function($scope, $localStorage, UserService, $state) {
$scope.sendValues = function(wallets){
if ($scope.myForm.$valid) {
...
} else {
$scope.myForm.submitted = true;
}
},
$scope.sendValue = function(wallet){
if (wallet.value == null) {
$scope.myForm.submitted = true;
} else {
...
}
}
})
You need to create a form for each wallet
This is due to your html name attributes has same value inside ng-repeat
Use $index in your name field for differentiate all the name attribute.
<form name="myForm" ng-submit="sendValues(wallets)" ng-controller="valuesCtrl" novalidate>
<div class="row" ng-repeat="wallet in wallets">
<div class="col item item-input-inset">
<label class="item-input-wrapper item-text-wrap">
<input name="wallet_{{$index}}" type="number" ng-model="wallet.value" type="text" required/>
</label>
<span ng-show="myForm.wallet_{{wallet.id}}.$error.required">!!!</span>
</div>
<div class="col item">{{ wallet.previous }}</div>
<button ng-click="sendValue(wallet)">
<i class="ion-android-send"></i>
</button>
<span class=ng-show="myForm.$submitted==true && myForm.wallet_{{$index}}.$error.required">Required</span>
</div>
<button class="button" type="submit">Submit</button>
</form>
You have to create a form inside form again. But as per HTML standard you can not have nested form. But angular provided that ability to have nested form but the inner form should be ng-form. Which mean you are going to wrap form & inside that you can find multiple ng-form's.
So you should have ng-form="innerForm" which will keep track of each repeated form.
Other thing which I observed is, you did mistake while using ng-show(you had {{}} inside ng-show expression, which would not work). To fix it you could access object via its key like ng-show="innerForm['wallet_'+wallet.id].$error.required"
Markup
<form name="myForm" ng-submit="sendValues(wallets)" ng-controller="valuesCtrl" novalidate>
<div ng-form="innerForm" class="row" ng-repeat="wallet in wallets">
<div class="col item item-input-inset">
<label class="item-input-wrapper item-text-wrap">
<input name="wallet_{{wallet.id}}" type="number" ng-model="wallet.value" type="text" required/>
</label>
<span ng-show="innerForm['wallet_'+wallet.id].$error.required">!!!</span>
</div>
<div class="col item">{{ wallet.previous }}</div>
<button ng-click="sendValue(wallet)">
<i class="ion-android-send"></i>
</button>
<span class=ng-show="innerForm.$submitted==true && innerForm['wallet_'+wallet.id].$error.required">Required</span>
</div>
<button class="button" type="submit">Submit</button>
</form>

form-control attribute is not adjusting to bootstrap modal template

I am trying to create a modal with form using angularjs and bootstrap.
First I created the form and now I am trying to put it to modal template but the form-control is sliding out of the modal as you can see in the link attached.
<div class="modal-header">
<h3 class="modal-title">Add New Review</h3>
</div>
<div class="modal-body">
<form role="form">
<fieldset>
<legend>Basic Information</legend>
<div class="container">
<div class="form-group">
<label for="address">Address</label>
<input type="text" id="address" name="address" class="form-control col-sm-1"
ng-model="editableReview.address"
required>
</div>`enter code here`
</fieldset>
</form>
</div>
<div class="modal-footer">
<div class="col-sm-offset-10">
<input type="button" class="btn btn-default" value="Cancel" ng-click="cancelForm()"/>
<input type="submit" class="btn btn-primary" value="Submit" ng-click="submitForm()"/>
</div>
</div>
this is what I get:
It seems like your problem is with the div class, specifically the container. I think you should try to delete this line:
<div class="container">
(and ofcourse its closing tag: </div>, and see if it fixes your issue.
Let me know if that helps.

Issue with ng-model and ng-repeat, duplicate forms

I have a page where multiple forms are created based on ng-repeat. Everything works fine until write something into the input and everything gets duplicated on all the other repeated forms input elements. I have used ng-model="Notify.message" which is nothing but object which takes the value from the input and sends to control on button submit and hence rest of the logic.
I am looking for when if one form is been filled, other forms should keep quite and shouldn't duplicate the values written in input text of form 1.
Here is the code:
<div data-ng-show="alluserposts.length > 0">
<div id="b{{userpost.id}}" data-ng-repeat="userpost in alluserposts" >
<div class="row" style="margin-left: -5px">
<form class="text-center" role="form" id=f1{{userpost.id}} name="userForm"
ng-submit="notify(userForm.$valid, userpost, apiMe)" novalidate>
<div class="row">
<div class="col-xs-8 col-md-4">
<div class="form-group">
<input data-container="body" data-toggle="popover" data-placement="top"
data-content="Any message which you would like to convey to post owner"
type="text" ng-model="Notify.message" data-ng-init="Notify.message=''"
id="u{{userpost.id}}"
placeholder="Enter a Message or Phone number" class="form-control"
required>
<p ng-show="userForm.name.$invalid && !userForm.name.$pristine" class="help-block">It is
required.</p>
<script>$(function () {
$("[data-toggle='popover']").popover();
});
</script>
<input type="hidden" ng-model="Notify.loggedInEmail"
ng-init="Notify.loggedInEmail = result.email"/>
<input type="hidden" ng-model="Notify.postId" ng-init="Notify.postId = userpost.id"/>
<input type="hidden" ng-model="Notify.destEmail"
ng-init="Notify.destEmail = userpost.userEmail"/>
</div>
</div>
<div ng-show="loginStatus.status == 'connected'" class="col-xs-4 col-md-2">
<button class="btn btn-primary" ng-disabled="userForm.$invalid || !userForm.$dirty"
type="submit">
Notify Post Owner
</button>
</div>
</div>
</form>
</p>
</div>
</div>
</div>
</div>
Issue fiddle - jsfiddle
Here you can when something is written in one input, other gets filled too :( . Also Notify is a Java mapped object and message is a variable inside it. Pls let me know how can this can be segragated!
You bind all of your inputs to same variable on $scope.
You must bind every text box to a distinct variable on $scope:
View:
<ul ng-repeat="post in posts">
<li>{{$index}}
<input type="text" ng-model="emails[$index]"/>
</li>
</ul>
Controller:
$scope.emails = [];
I am also at the starting phase of angularjs.
I have faced the same issue few days ago and resolved it by providing dynamic model name in ng-model like
<input type="text" ng-model="Notify[post.userEmail]" ng-init="Notify[post.userEmail] = post.userEmail" />
Working fiddle: Fiddle

Angular.js What is the best way to determine which button caused submit?

I have two buttons on a simple login form in a dropdown on a header bar that is outside of the view/content part of my single page app. There are two buttons on the form:
EDIT: both buttons need to submit the form, but I have two different outcomes; one does new member sign-up, the other login existing members. I do not want to handle this on multiple partials.
My Website
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav navbar-right">
<li class="active">
Home
</li>
<li class="divider-vertical"></li>
<li>
<div class="btn-group btn-group-xs navbar-btn btn-pad">
NL
FR
EN
</div>
</li>
<li class="divider-vertical"></li>
<!-- Begin Login Section -->
<li class="dropdown">
<a class="dropdown-toggle" href="#" data-toggle="dropdown">Signup/Login <strong class="caret"></strong></a>
<div class="dropdown-menu">
<div class="accountForm">
<!--form action="#" method="post" role="form"-->
<form name="loginForm" ng-submit="login()" ng-controller="homeController">
<div class="form-group">
<label class="control-label" for="username">Username</label>
<input type="text" ng-model="credentials.username" name="username" class="form-control input-sm" placeholder="username" required/>
</div>
<div class="form-group">
<label class="control-label" for="password">Password</label>
<input type="password" ng-model="credentials.password" name="password" class="form-control input-sm" placeholder="password" required/>
</div>
<div class="form-group">
<label class="control-label" for="remember">
<input type="checkbox" class"form-control" name="remember" value="1"/>Remember me</label>
</div>
<div class="form-group btn-group-justified">
<div class="btn-group">
<button button-id="join" type="submit" class="btn btn-default">New? Join us</button>
<input type="hidden" class="btn" />
</div>
<div class="btn-group inline">
<input type="hidden" class="btn" />
<button button-id="login" type="submit" class="btn btn-primary active">Log in</button>
</div>
</div>
</form>
</div>
</div>
</li>
<!-- End Login Section -->
</ul>
</div>
<!--/.nav-collapse -->
</div>
</div>
<div id="page" ng-view>
The first button is intended to send the user to the login process (if they are already registered) and the second button is for new users to register.
The problem I have is that if I use the <form ng-submit="myFunction()"> directive, I haven't yet found a way to determine the button that was pressed.
I can alternatively create my own directive, where I can determine the button that was pressed, but this seems to be a lot of coding effort by comparison, and is this really the Angular way?
app.directive('buttonId', function() {
return {
restrict: "A",
link: function(scope, element, attributes) {
element.bind("click", function(){
// when attributes.buttonId = 'join'
//call the create script
// when attributes.buttonId = 'login'
//call the authenticate script
});
}
}
});
So my question is simply using ng-submit="myfunction()"can i determine which button was pressed?
I know I am answering my own question, but this seems to be the "correct" way to do this:
<form name="loginForm" ng-submit="login()" ng-controller="homeController">
<div class="form-group btn-group-justified">
<div class="btn-group">
<button type="submit" class="btn btn-default" button-id="join">New?Joinus</button>
<input type="hidden" class="btn" />
</div>
<div class="btn-group inline">
<input type="hidden" class="btn" />
<button type="submit" class="btn btn-primary active" button-id="login">Log in</button>
</div>
</div>
</form≥
The above is the section of the form that I'm interested in. Note that both buttons have type="submit"and not type="button" . This is important for two reasons:
1) you can use the standard HTML5 form validation options when you click the buttons
2) it forces the ng-submithandler.
First the controller
app.controller('homeController', function($scope){
$scope.buttons = { chosen: "" };
$scope.login = function (){
// can get the button that was clicked as it is now added to the scope
// by the directive
alert($scope.buttons.chosen);
};
});
... and now the directive.
Next I handle the click on either button using a directive. This has the purpose of allowing me to identify the button, and pass it to the $scope. This was actually the main purpose of the excercise, but I realised that I could now bind this to anything where I suspected a click and pass some data to the scope.
app.directive('buttonId', function() {
return {
restrict: "A",
link: function(scope, element, attributes) {
element.bind("click", function(){
// able to get the name of the button and pass it to the $scope
// this is executed on every click
scope.buttons.chosen = attributes.buttonId;
// alert(attributes.buttonId + scope.buttons.chosen);
});
}
}
});
I am not sure if i have understood your problem correct but you can differential based on
Calling different function for each ng-submit such as ng-submit="myFunction1()" and ng-submit="myFunction2()"
You can also do the same passing in context using a parameter ng-submit="myFunction(from)"
You can also pass in special $event object as parameter ng-submit="myFunction($event)". This object contains the target information.
You can get a handle to the $event in your ng-click, and get its target, and then get its id, but I wouldn't recommend that it is not the angular way of doing things:
<input type="submit" id="test" data-ng-click="showAlert($event)">
Click Me
</button>
$scope.showAlert = function(event){
alert(event.target.id);
}
Another way is to set property dirty for this button and then to check which of the buttons is dirty.
For example if you have a form named "myForm" you can write something like this:
<form name="myForm" id="myForm" ng-submit="save()" ng-model="myForm" novalidate>
<input type="submit" name="save" ng-model="btnSave" ng-click="(frmForm.save.$setDirty())" />
<input type="submit" name="saveOut" ng-model="btnSaveOut" ng-click="(frmForm.saveOut.$setDirty())" />
</form>
In Javascript file you can handle it by:
if ($scope.btnSave.$dirty){
alert("First was clicked)}
else{
alert("First was clicked)}
}

Resources