ng-form with $setPristine() - javascript

<tr ng-form="fbForm_{{$index}}">
<td><center><p ng-hide="fb.editMode">{{fb.clientId}}</p>
<input type="text" class="form-control" name="clientId" ng-show="fb.editMode" required
ng-model="fb.clientId"/></center>
<span ng-show="fbForm_{{$index}}.clientId.$dirty && fbForm_{{$index}}.clientId.$error.required">Client Id is required.</span>
</td>
<td><center><p ng-hide="fb.editMode">{{fb.clientSecret}}</p>
<input type="text" class="form-control" name="clientSecret" ng-show="fb.editMode" required
ng-model="fb.clientSecret"/></center>
<span ng-show="fbForm_{{$index}}.clientSecret.$dirty && fbForm_{{$index}}.clientSecret.$error.required">Client secret is required.</span>
</td>
<td style="width:10%">
<p ng-hide="fb.editMode"><a ng-click="toggleEdit()" href="javascript:;">Edit</a> | <a ng-click="deletefacebook()" href="javascript:;">Delete</a></p>
<p ng-show="fb.editMode"><a class="btn btn-primary simple_button" ng-disabled="fbForm_{{$index}}.$pristine || fbForm_{{$index}}.$invalid" data-ng-click="save($index); fbForm_{{$index}}.$setPristine()" href="javascript:;">Save</a> | <a class="btn btn-primary simple_button" ng-click="cancel($index,fb.fbConfigId)" href="javascript:;">Cancel</a></p>
</td>
</tr>
http://plnkr.co/edit/LnnJQj1WwQaxLjlIWXq2?p=preview
for ng-disabled I am able to use {{$index}}
Getting syntax error in pristine function form name.

ngDisabled and ngClick directives expect expressions, so it should be something like this:
ng-disabled="this['fbForm_' + $index].$pristine || this['fbForm_' + $index].$invalid"
ng-click="save($index); this['fbForm_' + $index].$setPristine()"

Related

Setting an input value on page load in Angular

I want to set the value of my input value to 1 when the the page is loaded. But the box is empty when I execute the code.
<tr *ngFor="let item of cartItems; let i=index">
<td class="cart_product"><img class="img-fluid" [src]="item.image" alt=""></td>
<td class="cart_description">
<h3 class="product-name">{{item.title}} </h3>
<h6><strong><span class="mdi mdi-approval"></span> Available in</strong> - 500 gm</h6>
</td>
<td class="availability in-stock"><span class="badge badge-success">Checkers</span></td>
<td class="price"><span>${{item.price}}</span></td>
<td class="qty">
<div class="input-group">
<span class="input-group-btn"><button [disabled]="cartItems[i].quantity == 0" class="btn btn-theme-round btn-number" type="button" (click)="reduceQuantity(i)">-</button></span>
<input type="text" max="10" min="1" value="1" class="form-control border-form-control form-control-sm input-number" name="quantity" [(ngModel)]="cartItems[i].quantity">
<span class="input-group-btn"><button class="btn btn-theme-round btn-number" type="button" (click)="addQuantity(i)">+</button>
</span>
</div>
</td>
<td class="price"><span>{{getQuantity(i)}}</span></td>
<td class="action">
<a class="btn btn-sm btn-danger" data-original-title="Remove" href="#" title="" data-placement="top" data-toggle="tooltip"><i class="mdi mdi-close-circle-outline"></i></a>
</td>
</tr>
Even though you've set the value property of the input to 1, you are seeing an empty box because cartItems[i].quantity is undefined. Therefore the ngModel quickly changes that box to empty.
You used bi-directional binding on your input:
[(ngModel)]="cartItems[i].quantity"
Ideally it should set default value as 0 in your backend else you can set it's value to 0 in your component.ts file like setting values in cartItem:
cartItems.map(function(cartItem) {
if(!cartItem.quantity) {
cartItem.quantity = 0;
}
});

serializeArray is not picking up dynamically created form

I have reviewed many Stack overflow threads on this topic most especially this one
jQuery serializeArray not picking up dynamically created form elements, but none was able to solve the problem
I am searching through firebase database for a match. if there is a match form A is presented but if there is no match, form B is presented.
return CatalogueDB.ref('/FSC/Misc/' + splitinput[index]).once('value').then(function(snapshot) {
console.log(snapshot.val())
var key = snapshot.val().NSN
var Name = snapshot.val().Nomenclature
var resultcard = `
<form id="myform">
<tr class="tr-shadow">
<td style="width: 90px;">
<div>${key}
</div>
<div>
<br>
<button type="button" class="btn btn-secondary mb-1 btn-sm" data-toggle="modal" data-target="#mediumModal">
Add Photos
</button>
</div>
</td><td>
<span class="block ">
${Name}
</span>
</td>
<td class="desc">
<input class="au-input au-input--sm" type="text" name="search" placeholder="i.e. 20 EA" style="width: 100px;" />
</td>
<td>
<span class="status--process">
<input class="au-input au-input--sm" type="text" name="search" placeholder="Search for datas & reports..." style="width: 90px;" />
</span>
</td>
<td>
<button type="button" class="btn btn-primary btn-md" onclick="postitem(this);">Submit</button>
</td>
</tr>
</form>
<tr class="spacer"></tr>
`
container.innerHTML += resultcard;
})
.catch(function(error) {
container.innerHTML += "";
var errorcard = `
<form id="myform">
<tr class="tr-shadow">
<td style="width: 90px;">
<div>${splitinput[index]}
</div>
</td>
<td>
<span class="status--process">
<input class="au-input au-input--sm" type="text" name="search" placeholder="Search for datas & reports..." style="width: 90px;" />
</span>
</td>
<td>
<span class="status--process">
<input class="au-input au-input--sm" type="text" name="search" placeholder="Search for datas & reports..." style="width: 90px;" />
</span>
</td>
<td class="desc">
<input class="au-input au-input--sm" type="text" name="search" placeholder="Search for datas & reports..." style="width: 90px;" />
</td>
<td>
<button type="button" class="btn btn-primary btn-md" onclick="postitem(this)">Submit</button>
</td>
</tr>
</form>
`
container.innerHTML += errorcard;
})
});
I want to get the input value from the form when submit button is clicked, hence this function
function postitem() {
var data = $('#myform').serializeArray();
console.log(data)
}
the problem is that it only shows empty array [] in console log.
The input values are not retrieved and displayed. How do I capture the input value onclick of the submit button
I'm wondering if one of these things might be causing the problem? I could be wrong but might be worth checking:
1.
Isn't the correct syntax this?
document.getElementById('container').innerHTML += resultcard;
.....instead of this?
container.innerHTML += resultcard;
2.
When including html in a JavaScript file, should the quotes around your html be implemented like this? (Also note the use of the 'standard quote' marks as opposed to using `back quote` marks.)
var resultcard =
'<form id="myform">' +
'<tr class="tr-shadow">' +
'<td style="width: 90px;">' +
.
.
.

ng-repeat duplicates ng-click function

so I created a button to open a calendar with an ng-click function:
<button type="button" class="btn btn-default" ng-click="main.open_date()">
<i class="glyphicon glyphicon-calendar"></i>
</button>
I put it inside an ng-repeat, and when I added more fields & tested the button, this happened:
Aren't rows created by ng-repeat unique because they have their own index?
What am I missing here?
update: here is the code for my main.open_date():
me.open_date = function(key){
if(!key){key='date';}
me.uibdates[key] = true;
}
template code:
<tr ng-repeat="detail in main.employee_details track by $index">
<td>
<ui-select ng-model="detail.status" theme="bootstrap">
<ui-select-match placeholder="Select status" allow-clear>{$$select.selected.name$}</ui-select-match>
<ui-select-choices repeat="status in main.status | propsFilter: {name: $select.search} | limitTo: 100">
<div ng-bind-html="status.name | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
</td>
<td>
<p class="input-group">
<span class="input-group-btn">
<button type="button" class="btn btn-default"
ng-click="main.open_date()">
<i class="glyphicon glyphicon-calendar"></i>
</button>
</span>
<input type="text" class="form-control" placeholder="Select date"
uib-datepicker-popup="MM/dd/yyyy"
ng-model="detail.date" is-open="main.uibdates['date']"
ng-change="main.date_change()" />
</p>
</td>
<td>
<input type="text" class="form-control" ng-model="detail.remark" placeholder="">
</td>
<td>
<button style="display: inline; width: 35px;"class="form-control btn btn-primary btn-sm" ng-click="main.add_field($index);" ng-if="$index == (main.employee_details.length - 1)">
<span class="glyphicon glyphicon-plus"></span>
</button>
<button style="display: inline; width: 35px;" class="form-control btn btn-danger btn-sm" ng-click="main.delete_field($index);" ng-if="main.employee_details.length != 1">
<span class="glyphicon glyphicon-trash"></span>
</button>
</td>
</tr>
In my imagine, you can customize your code:
HTML:
<div ng-repeat="item in listItems track by item.id + $index">
<input class="datetime-picker" id="datepicker_{{item.id}}" />
<button ng-click="main.open_date(item.id)" class="open-datetime-picker">Open</button>
</div>
Angularjs
main.open_date = function(id){
$("datepicker_" + id).datetimepicker();
}
Everything inside the ng-repeat are repeated except the index. If you didn't use the index, the button is not unique.
in function main.open_date() can you use id instead class or html tags
like this
$('#datetimepicker1').datetimepicker();
Did you add $index in ng-repeat? Example: <div ng-repeat="item in listItems track by $index"></div>
Or, if your item have an ID field: <div ng-repeat="item in listItems track by item.id + $index"></div>

Angularjs ng-submit not working inside ng-repeat form

I have this form
<tr ng-repeat="quote in quotes">
<form ng-submit="submit()" name="qut">
<td class="text-left">
{[{ quote.business_name }]}
</td>
<td class="text-left">
<span ng-if="quote.quote">
{[{ quote.quote }]}
</span>
<span ng-if="!quote.quote">
<input ng-model="qt" class="form-control" type="text" name="quote" />
</span>
</td>
<td class="text-left">
<span ng-if="quote.status==1">
<input type="submit" class="btn btn-out" value="Quote" />
</span>
</td>
</form>
</tr>
In my controller I have
$scope.submit = function() {
console.log('form');
};
If I change ng-submit="submit()" to ng-click="submit()" in button it works, not sure why I am unable to submit the form
The problem is that you have an illegal html structure by nesting a table > tr element with a form. That causes the inner input[type=submit] not to identify his parent form and trigger the submit.
I could get your example working by replacing tables and tr with div and td with spans.
angular.module('myApp', [])
.controller('myController', function($scope) {
$scope.quotes = [{
business_name: "business_name 1",
quote: "quote1",
status: 1
}, {
business_name: "business_name 2",
quote: "quote2",
status: 1
}]
$scope.submit = function() {
console.log('form');
};
});
angular.element(document).ready(function() {
angular.bootstrap(document, ['myApp']);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-controller="myController">
<div ng-repeat="quote in quotes">
<form ng-submit="submit()" name="qut{{$index}}">
<span class="text-left">
{{ quote.business_name }}
</span>
<span class="text-left">
<span ng-if="quote.quote">
{{ quote.quote }}
</span>
<span ng-if="!quote.quote">
<input ng-model="qt" class="form-control" type="text" name="quote" />
</span>
</span>
<span class="text-left">
<span ng-if="quote.status==1">
<input type="submit" class="btn btn-out" value="Quote" />
</span>
</span>
</form>
</div>
</div>
Because multiple same form names are being created.
What you should do is you can create dynamic form names inside ng-repeat.
<tr ng-repeat="quote in quotes">
<form ng-submit="submit(qut{{$index}}.$valid)" name="qut{{$index}}">
<td class="text-left">
{[{ quote.business_name }]}
</td>
<td class="text-left">
<span ng-if="quote.quote">
{[{ quote.quote }]}
</span>
<span ng-if="!quote.quote">
<input ng-model="quote.quote" class="form-control" type="text" name="quote{{$index}}" />
</span>
</td>
<td class="text-left">
<span ng-if="quote.status==1">
<input type="submit" class="btn btn-out" value="Quote" />
</span>
</td>
</form>
</tr>
$scope.submit = function(value) {
console.log('form',value);
};

Optimize / Speed Up AngularJS HTML rendering - Performance Issue

This is probably not the first question on this topic, but since it took me hours finding out I couldn't find a good solution, I still want to ask you guys here.
I would like to optimize following code, because the page needs a few seconds to load right now. If I take that part out of the page (it is only one part of it), the page loads in max 1 second.
FYI: I only have 4 routes for the student that I test my application with.
<tr ng-repeat="route in student.itin">
<td>
<select ng-options="airline._id as airline.code for airline in ::airlines | orderBy: 'code'" ng-model="route.airline" class="form-control"/>
</td>
<td>
<input type="text" ng-model="route.flight_number" maxlength="4" size="4" class="form-control"/>
</td>
<td>
<input type="text" ng-model="route.class" maxlength="1" size="1" class="form-control"/>
</td>
<td>
<select ng-options="airport._id as airport.code for airport in ::airports | orderBy: 'code'" ng-model="route.departure.airport" class="form-control"/>
</td>
<td>
<div class="form-group has-feedback" ng-class="{'has-error': route.arrival.date < route.departure.date}">
<input type="text" class="form-control" is-open="datepickers['departure_date' + $index]" max-date="route.arrival.date" timepicker-options="timepicker_options" ng-focus="open($event, 'departure_date'+$index)" datetime-picker="{{ ::datetimepicker_format }}" ng-model="route.departure.date" />
<span ng-if="route.arrival.date < route.departure.date" tooltip-placement="right" tooltip="Arrival Date cannot be before Departure Date" tooltip-trigger="mouseenter" class="glyphicon glyphicon-remove form-control-feedback" aria-hidden="true"></span>
</div>
</td>
<td>
<select ng-options="airport._id as airport.code for airport in ::airports | orderBy: 'code'" ng-model="route.arrival.airport" class="form-control"/>
</td>
<td>
<div class="form-group has-feedback" ng-class="{'has-error': route.arrival.date < route.departure.date}">
<input type="text" class="form-control" is-open="datepickers['arrival_date' + $index]" min-date="route.departure.date" timepicker-options="timepicker_options" ng-focus="open($event, 'arrival_date'+$index)" datetime-picker="{{ ::datetimepicker_format }}" ng-model="route.arrival.date" />
<span ng-if="route.arrival.date < route.departure.date" tooltip-placement="right" tooltip="Arrival Date cannot be before Departure Date" tooltip-trigger="mouseenter" class="glyphicon glyphicon-remove form-control-feedback" aria-hidden="true"></span>
</div>
</td>
<td>
<input type="text" ng-model="route.filekey" class="form-control"/>
</td>
<td class="text-right">
<a class="btn btn-danger" ng-click="deleteRoute($index)" tooltip-placement="top" tooltip="Delete route" tooltip-trigger="mouseenter">
<i class="fa fa-trash-o"></i>
</a>
</td>
</tr>
What I have learned from my research is pretty much that I shouldn't use too much ng-repeat, try to minimize data-binding and filters. But after applying everything I have learned, I came up with the code above and don't know how to go on optimizing, since this is not enough.
Thank you
add track by to your ng-repeat
remove filters where it is possible
use one time binding with ::
Or switch to ReactJS.
Try to improve ng-repeat if your AngularJS is above 1.4.1: https://docs.angularjs.org/api/ng/directive/ngRepeat#tracking-and-duplicates
You can try to use sly-repeat directive instead ng-repeat: http://blog.scalyr.com/2013/10/angularjs-1200ms-to-35ms/

Categories