I'm developing a dotnetnuke 7 module using AngularJS.
Here is my code in View.ascx:
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<h2>Validation Example</h2>
<form ng-app="myApp" ng-controller="validateCtrl"
name="myForm" novalidate>
<p>Username:<br>
<input type="text" name="user" ng-model="user" required>
<span style="color:red" ng-show="myForm.user.$dirty && myForm.user.$invalid">
<span ng-show="myForm.user.$error.required">Username is required.</span>
</span>
</p>
<p>Email:<br>
<input type="email" name="email" ng-model="email" required>
<span style="color:red" ng-show="myForm.email.$dirty && myForm.email.$invalid">
<span ng-show="myForm.email.$error.required">Email is required.</span>
<span ng-show="myForm.email.$error.email">Invalid email address.</span>
</span>
</p>
<p>
<input type="submit"
ng-disabled="myForm.user.$dirty && myForm.user.$invalid ||
myForm.email.$dirty && myForm.email.$invalid">
</p>
</form>
<script>
var app = angular.module('myApp', []);
app.controller('validateCtrl', function ($scope) {
$scope.user = 'John Doe';
$scope.email = 'john.doe#gmail.com';
});
</script>
The code is copied from W3School but it seems that the AngularJS is not working well. Here is my View's screenshot:
I have tried an AngularSJ simple example and it working good likes:
<div ng-app="" ng-init="firstName='John'">
<p>Name: <input type="text" ng-model="firstName"></p>
<p>You wrote: {{ firstName }}</p>
</div>
Why is my first block of code not working? Are there any issues regarding the "form" tag in my module?
The problem is that DNN already includes the <form> tag (via Default.aspx), and nesting form tags isn't permitted.
A solution is to use <ng-form> as a substitute. eg:
...
<div ng-app="myApp" ng-controller="validateCtrl">
<ng-form name="myForm">
<p>Username:
<input type="text" name="user" ng-model="user" required>
<span style="color:red" ng-show="myForm.user.$dirty && myForm.user.$invalid">
<span ng-show="myForm.user.$error.required">Username is required.</span>
</span>
</p>
<p>
<input type="submit" ng-disabled="myForm.user.$dirty && myForm.user.$invalid">
</p>
</ng-form>
</div>
...
Also, you'll want to turn off HTML 5 default form validation since you're using Angular validation methods (this query works in DNN):
$(function() {
$('#Form').attr('novalidate', 'novalidate');
});
Further reading:
ngForm directive in AngularJS docs
Forms: Official AngularJS docs have better examples
Please be aware that the W3School example does not use best practices, and will introduce bad habits for the inexperienced (specifically, it doesn't include a '.' in ng-model which help avoid potential parent/child scope issues down the track. See the Forms examples in the link for a more robust approach.)
The form tag is certainly an issue when running within DNN/ASP.NET Webforms. I did a tutorial on DNNHero.com on building Angular applications as DNN modules.
Two pieces of advice:
Use a div tag to add your angular controller directives:
<div id="userForm" ng-controller="validateCtrl" ng-init="init(<%=this.ModuleId%>)">
Don't hard-code the ng-app directive in your html. Instead use the bootstrap method for attaching your app.
<script type="text/javascript">
angular.element(document).ready(function () {
var moduleContainer = document.getElementById('userForm');
angular.bootstrap(moduleContainer, ["myApp"]);
});
</script>
Can you do what you need to do with DNN through its API? It is best to think of Angular applications as completely disconnected from the server, like an iOS or Android application would be. Templating through DNN and Angular is inviting pain. Who knows what your rendered HTML looks like - I'm sure DNN/ASP.NET mangles it.
If you can leverage DNN's API the right mindset would be "I'm building an Angular application that happens to use DNN for persistence".
Related
I am trying this ,
<div ng-form="sadadPaymentForm" class="sadadPaymentForm" ng-if="vm.isSadadEnabled" name="sadadPaymentForm" validate-popup-form>
<div ng-if="vm.isSadadEnabled">
<div class="credit-debit-card-div" ng-include="'sadadTemplate'" ng-show="vm.view_tab == 'tab7'">
</div>
</div>
</div>
<span ng-show="vm.view_tab=='tab7' && vm.isSadadEnabled">
<button type="button" class="primary inline pay-now" id="paynowbtn" ng-disabled="!vm.checked3 || vm.sadadPaymentForm.$invalid" ng-click="vm.payByVoucher();" analytics-on="click" analytics-event="uaevent" analytics-eventcategory="Payment" analytics-eventaction="PayNow"
analytics-eventlabel="Pay now">
Pay by sadad
</button>
</span>
And , my template in another html file
<script type="text/ng-template" id="sadadTemplate">
<input fieldlabel="Online Payment ID" type="text" name="onlinePaymentId" ng-model="vm.sadadpayment.onlinePaymentId" class="form-control input-type-text"
ng-model-options="{ debounce: 100 }" validationKey-required="PaymentAdress1IsRequired" required maxlength="200">
</script>
Here the vm.sadadPaymentForm.$invalid does not work but Indidual components validation works on blur on blur of input .
BUT , if I add vm to ng-form ,ie like this
<div ng-form="vm.sadadPaymentForm" class="sadadPaymentForm" ng-if="vm.isSadadEnabled" name="vm.sadadPaymentForm" validate-popup-form>
<div ng-if="vm.isSadadEnabled">
<div class="credit-debit-card-div" ng-include="'sadadTemplate'" ng-show="vm.view_tab == 'tab7'">
</div>
</div>
</div>
Here the vm.sadadPaymentForm.$invalid works but Indidual components validation fails on blur of input for eg, TypeError: Cannot read property 'onlinePaymentId' of undefined
Help me understand how can I make both individual validation and the final form validation work together.Angular Ver 1.5,cannot upgrade this now.Need a solution with 1.5.
Form name attribute should have sadadPaymentForm inspite of vm.sadadPaymentForm. Since you don't have form name specified correctly, validation is failing.
name="vm.sadadPaymentForm"
should be
name="sadadPaymentForm"
Ok found out the issue , its basically a scope issue.
replaced
ng-if="vm.isSadadEnabled"
with
ng-show="vm.isSadadEnabled"
ng-if was preventing the DOM from rendering thus killing the scope variable vm itself
I'm working on an Angular 4 app, where we present the user with a login. The login may fail, and on return, we listen for the error:-
.subscribe(error => {
this.error = error;
});
This shows fine and we show this:-
<div *ngIf="error">
<p class="error-message">{{ error.ExceptionMessage }}</p>
</div>
Above this is a standard input field for username and password with a class. I wanted to be able to add an error class to this without doing the following:-
<div *ngIf="error">
<input type="email" class="form-control" />
</div>
<div *ngIf="!error">
<input type="email" class="form-control error-field" />
</div>
Is there a better way than rendering the input twice, on each side of the if?
Thanks!
You can do this using the class binding:
<input type="email" class="form-control" [class.error-field]="error">
yeah there's a better way using ngClass attribute like this:
<input type="email" [ngClass]="{'form-control': true, 'error-field': error}" />
I believe you are looking for NgClass or NgStyle:
https://angular.io/api/common/NgClass
https://angular.io/api/common/NgStyle
So basically I have a form that uses some Angular, it is a register form and has quite a lot of fields so for a better user experience we decided to use angular to create a 'next' button half way through the form which takes the user to the second half of the form without refreshing the page. However, using basic validation like required is complicated because if the user misses something on the first page and then clicks the submit button on the second page, the 'this field is required' message will flash up but the user cannot see it because it appearing on the first screen.
Is there a way to validate each half of the form separately using something like angularJS or jquery validation plugin? I.e. can I validate the first half of the form when I click the 'next' button so the user cannot get onto the second half of the form without first filling in the first half.
Just a quick note: I tried using the Jquery Validation plugin but as I am also using angular so when I click the next button it does validate once, but then still allows me to move on to the next page.
Hope this question makes sense, cheers!
You can do this in angular way completely as you are using angular in your form. You can also add a check inside your submit function whether any field is invalid before sending the post request too.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<body>
<h2>Validation Example</h2>
<form ng-app="myApp" ng-controller="validateCtrl"
name="myForm" novalidate>
<div ng-show="!next">
<p>Username:<br>
<input type="text" name="user" ng-model="user" required>
<span style="color:red" ng-show="myForm.user.$dirty && myForm.user.$invalid">
<span ng-show="myForm.user.$error.required">Username is required.</span>
</span>
</p>
<p>Email:<br>
<input type="email" name="email" ng-model="email" required>
<span style="color:red" ng-show="myForm.email.$dirty && myForm.email.$invalid">
<span ng-show="myForm.email.$error.required">Email is required.</span>
<span ng-show="myForm.email.$error.email">Invalid email address.</span>
</span>
</p>
<input type="button" ng-disabled="myForm.user.$invalid || myForm.email.$invalid" ng-click="movenext()" value="Next" />
</div>
<div ng-show="next">
<input type="button" ng-click="prev()" value="Previous" /><br>
<p>Password:<br>
<input type="password" name="password" ng-model="password" required>
<span style="color:red" ng-show="myForm.password.$dirty && myForm.password.$invalid">
<span ng-show="myForm.password.$error.required">Password is required.</span>
</span>
</p>
<p>
<input type="submit"
ng-disabled="myForm.password.$invalid">
</p>
</div>
</form>
<script>
var app = angular.module('myApp', []);
app.controller('validateCtrl', function($scope) {
$scope.next = false;
$scope.movenext = function(){
$scope.next = true;
}
$scope.prev = function(){
$scope.next = false;
}
});
</script>
</body>
</html>
try:
$("#form").validate();
you can also chose which elements to try and validate using:
$("#form").validate().element("#id");
this will manually fire the validation process without submitting the results, and it will also let you chose what elements you want to validate.
Maybe you can use the keyup function. Something like this:
$("input[type='email']").keyup(function(evt){
validate($(this).val());
});
Where validate is a function where you check the input's value.
Anyway, if you want use the keyup function you can do something like this.
I'm trying to create a script type of text/ng-template to put my error messages template into $templateCache. I want this script file to be remote, in it's own file outside of the HTML.
<script type="text/ng-template" id="error-messages">
<span ng-message="required">This field is required.</span>
<span ng-message="min">This number must be larger than {{min}}.</span>
<span ng-message="max">This number must be smaller than {{max}}.</span>
<span ng-message="number">A number is required.</span>
<span ng-message="date">A date is required.</span>
</script>
Then in the HTML I want to reference this template that I believe should be in $templateCache and I can access it by Id.
<form name="userForm">
<div class="form-group">
<label for="requiredInput">Required</label>
<input type="text" class="form-control" id="required" name="requiredInput"
ng-model="user.required" required />
<div ng-messages="userForm.requiredInput.$error" ng-messages-include="error-messages"></div>
</div>
</form>
If i put the script inline with the HTML it works just fine but I want it to be in a remote file. When I move it to a remote file my HTML is unable to find my template error-messages.
This is my first Plunker I'm sharing. Please let me know if you can't get to it.
http://plnkr.co/edit/NgSm7piaECWBab1LOmp3?p=preview
Please check the plunker - http://plnkr.co/edit/luhUuZURCOeHSuEhi11x?p=info
angular.module('app', ['ngMessages'])
.run(function ($templateCache, $http) {
$http.get('scriptTemplate.html')
.then(function(response) {
$templateCache.put('error-messages', response.data);
})
})
Load the ng-messages-include template using $http in the run phase of the application and save it in the templateCache.
I am working on a problem that a client has come across, the javascript that they are using is causing a /* and /*]]>*/ to show up on the Login Tooltip. I have been looking for the cause and I am baffled by it. All I know is that it is being generated somehow by the JavaScript at This Page.
The plugin is using this template which doesn't have any of those characters in it:
<script type="text/template" id="api-login-btn-template">
<div id="api-signin">
<label for="api-signin-login">Login : </label><input type="text" id="api-signin-login" name="email" value="" title="e-mail address"/>
<label for="api-signin-pass">Password : </label><input type="password" id="api-signin-pass" name="password" value="" title="password"/>
<div class="sign-in-errors"></div>
<br/>
<button class="sign-in-btn"><span>Sign In</span> <span class="blue">▶</span></button>
</div>
<div id="api-signout" style="display:none">
<p>My Favorite Programs <span class="ltblue_link">▶</span></p>
<p>Application: <a id="api-app-status" href="https://secure.apistudyabroad.com/forms"></a></p>
<button class="sign-out-btn"><span>Sign Out</span></button>
</div>
</script>
The javascript file responsible for this feature is here. I believe the pop up starts at Line 400 with $('.pane-container').each(function() {
This is how your template looks like on generated page (view source in Firefox):
<script type="text/template" id="find-a-program-template">
/*<![CDATA[*/<div style="padding:20px;"><h2>
...
...
...<div class="clear"></div></div>/*]]>*/
</script>
Seems like PHP / WordPress adds that CDATA part to the template during page rendering, but jQuery plugin doesn't know how to ignore it and writes it down instead.
Btw, you also have a bunch of server side <?php the_time('m') ?> calls on the page, but that's probably unrelated.