I'm working on a front-end application with ES6 and Angular. I'm trying to create a searchbox with autocomplete, and I want to use a custom template for the options list using Angucomplete-alt.
I created a template, but the options still have the standard format, and the execution doesn't throw errors. The examples page doesn't have a sample template.
Can someone give me an example of how to create the template?
My searchbox:
<angucomplete-alt id="country-search"
placeholder="Search countries"
pause="100"
selected-object="selectedCountry"
local-data="getCountries()"
search-fields="name"
title-field="name"
minlength="1"
template-url="/country-list-item.html"
input-class="form-control form-control-small"></angucomplete-alt>
The template:
<div class="autocomplete-template">
<div class="left-panel" style="display: inline-block;">
<span class="flag-icon flag-icon-{{ ::data.isoCode | lowercase}}"></span>
</div>
<div class="right-panel" style="display: inline-block;">
<span ng-bind-html="$highlight($getDisplayText())"></span>
</div>
</div>
All suggestions are welcome.
Thank you.
I have solved it. I copied the template's code from the html code of the examples page:
<div class="angucomplete-holder" ng-class="{'angucomplete-dropdown-visible': showDropdown}">
<p>This is custom</p>
<input ng-model="searchStr"
ng-disabled="disableInput"
type="text"
placeholder="{{placeholder}}"
ng-focus="onFocusHandler()"
class="{{inputClass}}"
ng-focus="resetHideResults()"
ng-blur="hideResults($event)"
autocapitalize="off"
autocorrect="off"
autocomplete="off"
ng-change="inputChangeHandler(searchStr)"/>
<div class="angucomplete-dropdown" ng-show="showDropdown">
<div class="angucomplete-searching" ng-show="searching" ng-bind="textSearching"></div>
<div class="angucomplete-searching" ng-show="!searching && (!results || results.length == 0)" ng-bind="textNoResults"></div>
<div class="angucomplete-row" ng-repeat="result in results" ng-click="selectResult(result)" ng-mouseenter="hoverRow($index)" ng-class="{'angucomplete-selected-row': $index == currentIndex}">
<div ng-if="imageField" class="angucomplete-image-holder">
<img ng-if="result.image && result.image != ''" ng-src="{{result.image}}" class="angucomplete-image"/>
<div ng-if="!result.image && result.image != ''" class="angucomplete-image-default"></div>
</div>
<div class="angucomplete-title" ng-if="matchClass" ng-bind-html="result.title"></div>
<div class="angucomplete-title" ng-if="!matchClass">{{ result.title }}</div>
<div ng-if="matchClass && result.description && result.description != ''" class="angucomplete-description" ng-bind-html="result.description"></div>
<div ng-if="!matchClass && result.description && result.description != ''" class="angucomplete-description">{{result.description}}</div>
</div>
<div class="angucomplete-row" ng-click="selectResult({title: searchStr, originalObject: { name: searchStr, custom: true }})" ng-mouseenter="hoverRow(results.length)" ng-class="{'angucomplete-selected-row': results.length == currentIndex}">
<div class="angucomplete-title">Select custom country '{{ searchStr }}'</div>
</div>
</div>
</div>
Related
I have an event on google tag manager that should fire when a form is submitted successfully. The form is an embedded code from Cognito Forms. The page is hosted in squarespace. Using Google Tag Manager preview I can see all conditions are met once submissions with the exception of the function below, which should be "true" on successful submission, but for some reason it is false even if I submit form successfully.
What could be going wrong? This is the contact us form and below the function. Thanks a lot.
function areAllFieldsFilled(){
var requiredFields = document.getElementsByClassName('cognito')[0].getElementsByTagName('form')[0].getElementsByTagName('input');
var questions = document.getElementsByClassName('cognito')[0].getElementsByTagName('form')[0].getElementsByTagName('textarea')[0];
var check = 0;
if (questions == '') {
check++;
} else{
for (var i = 0; i < 3; i++) {
if (requiredFields[i].value == '') {
check++;
break;
}
}
}
if (check == 0) {
return true;
} else {
return false;
}
}
I inspected your form and it looks like there are 2 reasons why you are returning false for a filled in form.
As noted by James in the comments, you need to do questions.value == '' and not questions == ''
There is a hidden <input /> tag in the form you probably didn't notice. The value of that input is always empty string because it doesn't have a value. To quickly fix this, you can start your loop at 1. Side Note: the length of your loop should be requiredFields.length -1 (since we are now starting at 1 instead of 0) instead of hard coding 3
Here is a working example
document.addEventListener("DOMContentLoaded", function(event) {
document.getElementById("c-submit-button").addEventListener("click", areAllFieldsFilled);
});
function areAllFieldsFilled(event) {
event.preventDefault(); // For testing, REMOVE THIS
var requiredFields = document.getElementsByTagName('form')[0].getElementsByTagName('input');
var questions = document.getElementsByTagName('form')[0].getElementsByTagName('textarea')[0];
var check = 0;
if (questions.value == '') {
console.log("questions was empty");
check++;
} else {
for (var i = 1; i < requiredFields.length - 1; i++) {
if (requiredFields[i].value == '') {
check++;
break;
}
}
}
console.log(`check count is ${check}`);
if (check == 0) {
console.log("Returning True");
return true;
} else {
console.log("Returning False");
return false;
}
// or replace the above 7 lines with return check == 0
}
<form lpformnum="1">
<div class="c-forms-form" tabindex="0">
<div class="c-editor" style="display:none;">
<input type="text" class="c-forms-form-style" style=" background-repeat: no-repeat; background-attachment: scroll; background-size: 16px 18px; background-position: 98% 50%;">
</div>
<div class="c-forms-form-body">
<div class="c-forms-template" sys:attach="dataview" dataview:data="{binding entry, source={{ Cognito.Forms.model }} }">
<div class="c-forms-form-main c-span-24 c-sml-span-12">
<div class="c-section c-col-1 c-sml-col-1 c-span-24 c-sml-span-12" data-field="Section">
<div class="">
<div class="c-section c-col-1 c-sml-col-1 c-span-24 c-sml-span-12" data-field="Section">
<div class="">
<div class="c-name c-field c-col-1 c-sml-col-1 c-span-24 c-sml-span-12 c-required" data-field="Name">
<div class="c-label">
<label>Name</label>
</div>
<div>
<div class="c-offscreen">
<label for="c-0-12">First</label>
</div>
<div class="c-editor c-span-1" style="width: 50%; float: left;">
<input type="text" id="c-0-12" placeholder="First">
</div>
<div class="c-offscreen">
<label for="c-1-12">Last</label>
</div>
<div class="c-editor c-span-1" style="width: 50%; float: left;">
<input type="text" id="c-1-12" placeholder="Last">
</div>
</div>
<div class="c-validation">First and Last are required.</div>
</div>
<div class="c-email c-field c-col-1 c-sml-col-1 c-span-24 c-sml-span-12 c-required" data-field="PreferredEmailAddress">
<div class="c-label">
<label for="c-3-11">Preferred Email Address</label>
</div>
<div class="c-editor">
<input type="text" id="c-3-11">
</div>
<div class="c-validation">Preferred Email Address is required.</div>
</div>
<div class="c-phone c-phone-international c-field c-col-1 c-sml-col-1 c-span-12 c-sml-span-12 c-required" data-field="Phone">
<div class="c-label">
<label for="c-4-10">Phone</label>
</div>
<div class="c-editor">
<input type="text" id="c-4-10">
</div>
<div class="c-validation">Phone is required.</div>
</div>
<div class="c-yesno-radiobuttons c-field c-col-13 c-sml-col-1 c-span-12 c-sml-span-12" data-field="WouldYouLikeForUsToCallYou">
<legend class="c-label">Would you like for us to call you?</legend>
<div class="c-editor c-columns-0">
<label class="c-yesno-radio" for="c-5-8">
<input type="radio" name="group7" id="c-5-8" checked="checked"><span>Yes</span></label>
<label class="c-yesno-radio" for="c-5-9">
<input type="radio" name="group7" id="c-5-9"><span>No</span></label>
</div>
<div class="c-validation"></div>
</div>
<div class="c-text-multiplelines c-field c-col-1 c-sml-col-1 c-span-12 c-sml-span-12 c-required" data-field="Questions">
<div class="c-label">
<label for="c-6-6">Questions:</label>
</div>
<div class="c-editor">
<textarea id="c-6-6" type="text" height=""></textarea>
</div>
<div class="c-validation">Questions: is required.</div>
</div>
</div>
<div class="c-validation"></div>
</div>
</div>
<div class="c-validation"></div>
</div>
</div>
</div>
<div id="c-recaptcha-div"></div>
<div class="c-forms-error">
<div class="c-validation"></div>
</div>
<div class="c-button-section">
<div class="c-action">
<button class="c-button" id="c-submit-button">Submit</button>
</div>
</div>
</div>
<div class="c-forms-confirmation">
<div class="c-forms-confirmation-message c-html" sys:attach="dataview" dataview:data="{binding entry, source={{ Cognito.Forms.model }} }"><span><p><strong>Thank you for reaching out!</strong></p> <p>We look forward to being in touch with you soon.</p></span></div>
</div>
</div>
</form>
Some notes:
Using a more selective selector would be a more concrete approach.
I have a subscription feature which is open through checking a radio box. When open inside this section I have 2 radio buttons for subscribe the period weekly or monthly and below an item. When I pressing save the state of this period have to be saved for one item I have from the server. You can check the screenshot to see the view. Anyway, there is no save because the array result empty and that item is not in that array. My problem is I see the item below but somehow I'm not pushing it into the array with the period selected from radio buttons. I would like to receive help to understand why of that and what I should modify to make it works properly.
Please check the code I'm sharing controller and view:
searchApp.controller('UserSettingsCtrl', ['$scope', '$q', '$rootScope', 'aiStorage', 'userConfig', 'UserSettingsService', 'WebsiteSource', 'AnalyticsEmailService', 'toaster', '$translate', '$filter', 'ngTableParams',
function($scope, $q, $rootScope, store, userConfig, UserSettingsService, WebsiteSource, AnalyticsEmailService, toaster, $translate, $filter, ngTableParams) {
$scope.init = function() {
$scope.availableLanguages = {
da: 'Dansk',
en: 'English',
sv: 'Svensk'
}
window.scope = $scope
$scope.userInfo = store.get('user')
$scope.loadingAction = false
$scope.selectFlag = false
$scope.subscriptionEnginesFromServer = []
$scope.subscriptionEngines = []
$scope.analyticsEmailSettings = {}
$scope.engines = angular.copy(WebsiteSource.sites)
AnalyticsEmailService.getUserSubscription().then(
function success(response) {
$scope.loadingAction = false
$scope.subscription = response
console.log('response.data', response.data)
$scope.subscriptionEnginesFromServer = populateSubscribedEnginesFromServer(response.data)
getUnselectedEngines()
$scope.analyticsEmailSettings.subscribed = (response.data.length > 0)
},
function error() {})
}
function populateSubscribedEnginesFromServer(data) {
console.log('data', data)
var subscriptionEngines = []
for (var i = 0; i < data.length; i++) {
var subscription = data[i]
var engine = $scope.engines.filter(function(x) {
if (x.id === subscription.engine) {
var index = $scope.engines.indexOf(x)
$scope.engines[index].type = subscription.type
}
return x.id === subscription.engine
})[0]
console.log('engine', engine)
if (engine) subscription.name = engine.name
subscriptionEngines.push(subscription)
}
console.log('subscriptionEngines', subscriptionEngines)
if (subscriptionEngines.length == 0) {
$scope.analyticsEmailSettings.subscription = 'WeeklyAnalytics'
} else {
$scope.analyticsEmailSettings.subscription = subscriptionEngines[0].type
}
return subscriptionEngines
}
// Save for all always the user have to press the save button if wants save no auto save as it is now
$scope.save = function() {
$scope.loadingAction = true
if ($scope.analyticsEmailSettings.subscribed) {
AnalyticsEmailService.updatesubscriptions($scope.subscriptionEnginesFromServer, function success(response) {}, function error() {})
} else {
$scope.analyticsEmailSettings.subscription = 'WeeklyAnalytics'
$scope.subscriptionEnginesFromServer = []
AnalyticsEmailService.updatesubscriptions($scope.subscriptionEnginesFromServer, function success(response) {}, function error() {})
}
UserSettingsService.save({
userId: $scope.userInfo.id
}, $scope.userInfo, function() {
$scope.loadingAction = false
userConfig.setCurrentUserConfig($scope.userInfo)
userConfig.setUserLocale()
store.set('user', $scope.userInfo)
toaster.pop({
type: 'success',
body: $translate.instant('notifications_user_settings_changed_success')
})
}, function() {})
$scope.subscriptionEngines = []
}
// removeSelectedEngines
getUnselectedEngines = function() {
for (var i = 0; i < $scope.engines.length; i++) {
if ($scope.subscriptionEnginesFromServer.filter(function(x) {
return x.engine === $scope.engines[i].id
}).length == 0)
$scope.engines[i].type = ''
}
}
// #todo: consider referring by array key instead of engineId
function updatesubscriptions(engineId, subscriptionType) {
var engine
for (var i = 0; i < $scope.subscriptionEnginesFromServer.length; i++) {
if ($scope.subscriptionEnginesFromServer[i].engine == engineId) {
engine = $scope.subscriptionEnginesFromServer[i]
}
}
engine.type = subscriptionType
engine.engine = engineId
}
$scope.updateSubscriptionType = function(engine) {
for (var i = 0; i < $scope.subscriptionEnginesFromServer.length; i++) {
updatesubscriptions($scope.subscriptionEnginesFromServer[i].engine, $scope.analyticsEmailSettings.subscription)
}
}
$scope.addSubscribedEngine = function(engine) {
$scope.subscriptionEngines = []
engine.type = $scope.analyticsEmailSettings.subscription
$scope.subscriptionEnginesFromServer.push({
type: engine.type,
engine: engine.id,
name: engine.name
})
}
$scope.selectFirstUnsubscribedEngine = function() {
var filtered
filtered = $scope.engines.filter(function(x) {
return x.type == ''
})
filtered = $filter('orderBy')(filtered, 'name')
$scope.engine.current = filtered.length ? filtered[0] : null
}
$scope.removeSubscribedEngine = function(engine) {
engine.type = ''
for (var i = 0; i < $scope.subscriptionEnginesFromServer.length; i++) {
if ($scope.subscriptionEnginesFromServer[i].engine == engine.id) {
$scope.subscriptionEnginesFromServer.splice(i, 1)
}
}
save()
}
}])
View:
<div ng-controller="UserSettingsCtrl" ng-init="init()">
<div class="content">
<header class="flex-container row header">
<div class="flex-1">
<h1 class="flex-1">{{ 'user_settings_title' | translate }}</h1>
</div>
<!--<a class="logout" href ui-sref="account.settings.changepassword">{{ 'user_change_password_menu' | translate }}</a>-->
</header>
<div class="main-edit">
<div class="subsection">
<div class="inputs-container-row full-width">
<div class="input-group full-width">
<div class="inputfield">
<label class="label ng-binding" for="name">
{{ 'user_settings_firstname_label' | translate }}
</label>
<input type="text" name="firstname" ng-model="userInfo.firstName" class="flex-1" ng-class="{'first-letter-to-upper' : userInfo.firstName.length > 0 }" placeholder="{{ 'user_settings_firstname_placeholder' | translate }}">
</div>
</div>
<div class="input-group full-width">
<div class="inputfield">
<label class="label ng-binding" for="name">
{{ 'user_settings_lastname_label' | translate }}
</label>
<input type="text" name="lastname" ng-model="userInfo.lastName" class="flex-1" ng-class="{'first-letter-to-upper' : userInfo.lastName.length > 0 }" placeholder="{{ 'user_settings_lastname_placeholder' | translate }}">
</div>
</div>
</div>
<div class="inputs-container-row full-width">
<div class="inputs-container-row half-width">
<div class="input-group full-width">
<label class="label" for="name">{{ 'user_settings_language_label' | translate }}</label>
<div class="select-group full-width">
<select class="select" id="selectLanguage" ng-model="userInfo.language" ng-options="key as value for (key , value) in availableLanguages"></select>
<label for="selectLanguage"><span class="fa fa-angle-down"></span></label>
</div>
</div>
</div>
<div class="inputs-container-row half-width">
<div class="input-group full-width">
<label class="label" for="name">
{{ 'user_settings_phone_label' | translate }}
</label>
<input type="text" name="lastname" ng-model="userInfo.phoneNumber" placeholder="{{ 'user_settings_phone_placeholder' | translate }}">
</div>
</div>
</div>
</div>
<div class="subsection">
<div class="inputs-container-row half-width">
<div class="input-group full-width">
<label class="label" for="name">
{{ 'user_settings_password_label' | translate }}
<a ui-sref="account.settings.changepassword" class="button button-link--primary button--first">
{{ 'user_settings_password_button' | translate }}...
</a>
</label>
</div>
</div>
</div>
</div>
<div class="flex-container row header">
<div class="flex-1">
<h1 class="flex-1">{{ 'user_settings_emailStatistics_title' | translate }}</h1>
</div>
</div>
<!--||| Subscribe Start |||-->
<div class="main-edit">
<div class="subsection">
<div class="flex-container row">
<div class="radiobutton-group">
<div class="width-140">
<input id="subscribed" type="checkbox" ng-model="analyticsEmailSettings.subscribed" value="subscribed" class="radiobutton">
<label class="label highlight inline no-bottom-margin" for="subscribed">
{{ 'user_settings_emailStatistics_subscribe' | translate }}
</label>
</div>
</div>
</div>
<div ng-show="analyticsEmailSettings.subscribed">
<div class="flex-container row">
<div class="input-group flex-1" ng-switch="analyticsEmailSettings.subscription">
<label class="label" for="name">{{ 'user_settings_emailStatistics_recurrence' | translate }}</label>
<div class="inputs-container-row half-width" name="oftenReportSent">
<span class="radiobutton flex-1" ng-class="{'checked' : analyticsEmailSettings.subscription === 'WeeklyAnalytics'}" name="radio">
<input type="radio" name="WeeklyAnalytics" ng-model="analyticsEmailSettings.subscription" ng-change="updateSubscriptionType()" ng-checked="analyticsEmailSettings.subscription === 'WeeklyAnalytics'" value="WeeklyAnalytics" id="WeeklyAnalytics" ng-required="">
<label for="WeeklyAnalytics">{{ 'user_settings_emailStatistics_weekly' | translate }}</label>
</span>
<span class="radiobutton flex-1" ng-class="{'checked' : analyticsEmailSettings.subscription === 'MonthlyAnalytics'}">
<input type="radio" name="MonthlyAnalytics" ng-model="analyticsEmailSettings.subscription" ng-change="updateSubscriptionType()" ng-checked="analyticsEmailSettings.subscription === 'MonthlyAnalytics'" value="MonthlyAnalytics" id="MonthlyAnalytics" ng-required="">
<label for="MonthlyAnalytics">{{ 'user_settings_emailStatistics_monthly' | translate }}</label>
</span>
</div>
<div> <span style="color:red;" ng-show="analyticsEmailSettings.subscription == null">Please select option</span></div>
</div>
</div>
<h1>Before</h1>
<div ng-if="engines.length == 1">
<ul class="tags tags--inline item-with-inline-buttons">
<li ng-repeat="engine in engines | orderBy:'name'">
{{engine.name}}
<span class="button-icon button--primary button--delete" ng-click="removeSubscribedEngine(engine); selectFirstUnsubscribedEngine()">
<i class="fa fa-trash-o"></i>
</span>
</li>
</ul>
</div>
<h1>after</h1>
<div ng-show="engines.length > 1">
<div class="flex-container row" ng-show="((engines | filter:{type:''}:true).length != 0)">
<div class="input-group full-width">
<label class="label" for="selectEngine">
{{ 'user_settings_emailStatistics_engines_label' | translate }}:
</label>
<div class="half-width inputfield--horizontal" style="margin-bottom: 10px;">
<div class="full-width select-group" ng-if="(engines | filter:{type:''}:true).length > 0">
<select class="select" id="selectEngine" ng-model="$parent.engine.current" ng-options="website.name for website in engines | filter:{type:''}:true | orderBy:'name'" ng-init="$parent.engine.current = (engines | filter:{type:''}:true | orderBy:'name')[0]">
</select>
<label for="selectSubscription"><span class="fa fa-angle-down"></span></label>
</div>
<span ng-show="engines.length == 1">{{(engines | filter:{type:''}:true)[0].name}}</span>
<div id="btnAddWebSitesSubscription" ng-show="engines.length > 0" class="button button--add" ng-click="addSubscribedEngine(engine.current); selectFirstUnsubscribedEngine()"><i class="fa fa-plus"></i></div>
</div>
</div>
</div>
<div ng-model="successMessage" ng-show="showMessage" style="color:green;" class="message fadein fadeout">{{successMessage}}</div>
</div>
<h1 ng-show="subscriptionEnginesFromServer.length > 0 && engines.length > 1">Websites Subscribed</h1>
<div class="flex-container row" ng-if="subscriptionEnginesFromServer.length > 0 && engines.length > 1">
<ul class="tags tags--inline item-with-inline-buttons">
<li ng-repeat="engine in engines | filter:{type:'Analytics'} | orderBy:'name'">
{{engine.name}}
<span class="button-icon button--primary button--delete" ng-click="removeSubscribedEngine(engine); selectFirstUnsubscribedEngine()">
<i class="fa fa-trash-o"></i>
</span>
</li>
</ul>
</div>
</div>
</div>
<footer class="flex-container flex-end row footer">
<button class="button button--primary button--action" ng-click="save();">
<i ng-show="loadingAction" class="fa fa-spinner fa-spinner-custom"></i>
<span ng-show="!loadingAction">{{ 'general_save' | translate }}</span>
</button>
</footer>
</div>
</div>
Be careful of using ng-hide/ng-show as when the partial is 'hidden' it destroys the model (if there are any) contained within itself (so, use ng-if instead).
In your html in the subscription section, you make a call like this:
ng-change="updateSubscriptionType()"
But in your javascript you have:
$scope.updateSubscriptionType = function(engine) {
for (var i = 0; i < $scope.subscriptionEnginesFromServer.length; i++) {
updatesubscriptions($scope.subscriptionEnginesFromServer[i].engine, $scope.analyticsEmailSettings.subscription)
}
}
So it's expecting an 'engine' argument, which you never pass in. But looking at the code you don't use the engine argument anyway; you use the 'engine' property of $scope.subscriptionEnginesFromServer[i] but that's it.
It however, doesn't do anything that I can see, anyway. It loops through an empty array then calls updatesubscriptions() to do something, but it won't actually call it.
Also, the updatesubscriptions() method itself doesn't actually do anything. This is probably why you're not getting anything in your array. I'd suggest modifying your template slightly, because the subscription radio buttons are outside the engines loop, so you won't be able to associate the subscription type with any engine. Once you have done that, then the subscriptions type radio buttons will have access to 'engine', which you can pass in. Modify your method accordingly:
$scope.updateSubscriptionType = function(engine) {
if (!$scope.subscriptionEnginesFromService.includes(engine)) {
$scope.subscriptionEnginesFromService.push(engine);
}
updatesubscriptions(engine, $scope.analyticsEmailSettings.subscription);
}
And also modify the updatesubscriptions() slightly.
I want to hide the <span ng-show="currencyObject.to != 'undefined'">=</span> until the currencyObject.to is undefined which is supposed to be undefined until the user select an option from the select box.
I used ng-show="currencyObject.to != 'undefined'" to conditionally show-hide the span but it is not working. What I find is, when the page is freshly loaded, the = is visible.
<div class="row" ng-controller="QConvertController">
<div class="col-md-8 col-md-offset-2">
<div class="form-group">
<label for="amount">Amount</label>
<input type="number" step="any" class="form-control" id="amount" ng-model="currencyObject.amount">
</div>
</div>
<div class="col-md-8 col-md-offset-2">
<div class="form-group">
<label for="from">From</label>
<select class="form-control" id="from" ng-model="currencyObject.from" ng-change="getconvertedrate()">
<option ng-repeat="currencyCode in currencyCodes" value="{{currencyCode.value}}">{{currencyCode.display}}</option>
</select>
</div>
</div>
<div class="col-md-8 col-md-offset-2">
<div class="form-group">
<label for="to">To</label>
<select class="form-control" id="to" ng-model="currencyObject.to" ng-change="getconvertedrate()">
<option ng-repeat="currencyCode in currencyCodes" value="{{currencyCode.value}}">{{currencyCode.display}}</option>
</select>
</div>
</div>
<br>
<br>
<br>
<div class="col-md-8 col-md-offset-2">
<h1 class="display-4">{{currencyObject.amount}} {{currencyObject.from}} <span ng-show="currencyObject.to != 'undefined'">=</span> {{currencyObject.amount_converted}} {{currencyObject.to}}</h1>
</div>
</div>
QConvertController.js
var app = angular.module('qconvertctrlmodule', [])
.controller('QConvertController', function($scope, $http, $log) {
$scope.currencyObject = {};
$scope.currencyObject.from;
$scope.currencyObject.to;
$scope.currencyObject.amount;
$scope.currencyObject.amount_converted;
$scope.currencyObject.runCount = 0;
$scope.currencyCodes = [{value : 'INR', display : 'Indian Rupee'}, {value : 'USD', display : 'US Dollar'}, {value : 'GBP', display : 'British Pound'}];
$scope.getconvertedrate = function() {
$log.info("FROM : " + $scope.currencyObject.from);
$log.info("TO : " + $scope.currencyObject.to);
$http.get("http://api.decoded.cf/currency.php", {params : {from : $scope.currencyObject.from,
to : $scope.currencyObject.to, amount : $scope.currencyObject.amount}})
.then(function(response) {
$scope.currencyObject.amount_converted = response.data.amount_converted;
$log.info(response.data.amount_converted);
});
};
});
You don't need != 'undefined' to check the variable is defined or not
<span ng-show="currencyObject.to">=</span>
or
<span ng-hide="!currencyObject.to">=</span>
or
<span ng-if="currencyObject.to">=</span>
You can directly use as ng-show="currencyObject.to"
Also in Js correct usage of comparing with undefined is
if(typeof variable !== 'undefined'){ /*...*/ }
I've added validations for my form and I wanted it to trigger each and every validation when submit button is clicked. I tried googling for how to trigger them but it seems they are not working for me.
Here's my code for the form
<form id="CustomerForm" class="form-horizontal group-border stripped" name="CustomerDetails" novalidate ng-submit="CustomerDetails.$valid && AddCustomer()">
<div class="form-group" ng-class="{'has-error': CustomerDetails.cname.$invalid && !CustomerDetails.cname.$pristine}">
<label class="col-lg-2 col-md-3 control-label">Customer Name</label>
<div class="col-lg-10 col-md-9">
<input type="text" ng-model="CusDetails.cname" class="form-control" name="cname" id="cname" required />
<p ng-show="CustomerDetails.cname.$error.required && !CustomerDetails.cname.$pristine" class="help-block">Customer name required!</p>
</div>
</div>
<!--end of .form-group-->
<div class="form-group" ng-class="{'has-error': CustomerDetails.comname.$invalid && !CustomerDetails.comname.$pristine}">
<label class="col-lg-2 col-md-3 control-label">Company Name</label>
<div class="col-lg-10 col-md-9">
<input type="text" ng-model="CusDetails.comname" class="form-control" name="comname"id="comname" required />
<p ng-show="CustomerDetails.comname.$error.required && !CustomerDetails.comname.$pristine" class="help-block">Comapany name required!</p>
</div>
</div>
<!--end of .form-group-->
<div class="form-group" ng-class="{'has-error': CustomerDetails.ctel.$invalid && !CustomerDetails.ctel.$pristine}">
<label class="col-lg-2 col-md-3 control-label" for="">Telephone Number</label>
<div class="col-lg-10 col-md-9">
<div class="input-group input-icon">
<span class="input-group-addon"><i class="fa fa-phone s16"></i></span>
<input ng-model="CusDetails.tel" class="form-control" name="ctel" type="text" placeholder="(999) 999-9999" id="ctel" required >
<p ng-show="CustomerDetails.ctel.$error.required && !CustomerDetails.ctel.$pristine" class="help-block">Telephone number required!</p>
</div>
</div>
</div>
<!-- End .form-group -->
<div class="form-group" ng-class="{'has-error': CustomerDetails.email.$invalid && !CustomerDetails.email.$pristine}">
<label class="col-lg-2 col-md-3 control-label" for="">Email address</label>
<div class="col-lg-10 col-md-9">
<input ng-model="CusDetails.email" type="email" class="form-control" name="email" placeholder="someone#example.com" id="email" required >
<p ng-show="CustomerDetails.email.$error.required && !CustomerDetails.email.$pristine" class="help-block">Email is required!</p>
<p ng-show="CustomerDetails.email.$error.email && !CustomerDetails.email.$pristine" class="help-block">Please Enter valid email address.</p>
</div>
</div>
<!-- End .form-group -->
<div class="form-group">
<div class="col-lg-9 col-sm-9 col-xs-12">
<button name="btnSubmit" type="submit" class="btn btn-info pad"><span class="fa fa-user-plus"></span> Add Customer</button>
<button type="button" id="cancel" class="btn btn-default pad">Cancel</button>
</div>
</div>
</form>
UPDATE: I have change the code according to Adrian Brand but still no trigger. What am I doing wrong?
Here's my angularjs for the form. (controller)
(function () {
'use strict';
angular
.module('efutures.hr.controllers.customer', [])
.controller('AddCustomerController', AddCustomerController);
AddCustomerController.$inject = ['$scope', '$location', '$rootScope', '$http', 'CustService'];
function AddCustomerController($scope, $location, $rootScope, $http, CustService) {
(function initController() {
})();
$scope.AddCustomer = function () {
var CustomerDetails = {
cname: $scope.CusDetails.cname,
comname: $scope.CusDetails.comname,
tel: $scope.CusDetails.tel,
email: $scope.CusDetails.email
};
if ($scope.CustomerDetails.$valid) {
CustService.Customer(CustomerDetails, function (res) {
console.log(res);
$.extend($.gritter.options, {
position: 'bottom-right',
});
if (res.data == 'success') {
$.gritter.add({
title: 'Success!',
text: 'Successfully added the new customer ' + '<h4><span class="label label-primary">' + CustomerDetails.cname + '</span></h4>',
time: '',
close_icon: 'l-arrows-remove s16',
icon: 'glyphicon glyphicon-ok-circle',
class_name: 'success-notice'
});
$scope.CusDetails = {};
$scope.CustomerDetails.$setPristine();
}
else {
$.gritter.add({
title: 'Failed!',
text: 'Failed to add a new customer. Please retry.',
time: '',
close_icon: 'l-arrows-remove s16',
icon: 'glyphicon glyphicon-remove-circle',
class_name: 'error-notice'
});
}
});
}
}
}
})();
I even tried making the form submitted true, still didn't work.
The only thing that worked for me is the disabling the button until its validated but that isn't the requirement. I want it to trigger when the submit form is clicked. Help would be greatly appreciated.
In the click event where you wanted to trigger the validation, add the following:
vm.triggerSubmit = function() {
vm.homeForm.$setSubmitted();
...
}
This works for me. To know more about this click here : https://code.angularjs.org/1.3.20/docs/api/ng/type/form.FormController
Your problem lies in the fact that your submit button is not contained in the form so the form never gets submitted. You are just running the controller method via a click handler.
Form validation is not a controller concern and has no place in the controller. It is purely a view concern.
In your form you put a ng-submit="CustomerDetails.$valid && AddCustomer()" and take the click handler off the submit button and place the button row within the form. This way the view will only submit if the form is valid. Do not pollute your controllers with form validation and keep it all contained in your view. You should look into the controller as syntax and then you will not even have access to the $scope in your controllers.
I have this form and I have used ng-hide to hide some fields when meeting certain requirements. I have used validation for all the fields ( When a field is kept empty, it'll validate and ask to be fill the field). The problem is when my fields get hidden, still it seems to be validating. So I cannot proceed my form. How can I solve this problem?
I've used ng-required to the fields I've hidden and set it to false when that field is not needed, but it does not seem to work.
This is part of the form that I'm referring to:
<div class="form-group" ng-class="{ 'has-error' :submitted && (myForm.scheduler.$pristine || myForm.scheduler.$invalid)}">
<label class="labelColor"><h5><b>Payment Type *</b></h5></label>
<select type="select" class="textbox-n" id="scheduler" ng-model="data.scheduler" ng-change="scheduleChange()" ng-options="Scheduler.name for Scheduler in SchedulersArr" name="scheduler" required>
<option id="default" value="" selected="selected">--Select--</option></select>
<span class="help-inline" ng-show="submitted && (myForm.scheduler.$pristine || myForm.scheduler.$invalid)" >A Payment Type is required.</span>
</div>
<!-- Effective Date:-->
<div ng-hide = "hideFutureDate">
<div class="form-group" ng-class="{ 'has-error' : myForm.effectiveDate.$invalid && myForm.effectiveDate.$dirty && submitted || (myForm.effectiveDate.$invalid && myForm.effectiveDate.$pristine) && submitted }">
<label class="labelColor" ><h5><b>Effective Date*</b></h5></label><br>
<input style="width:100%" class="item-input-wrapper" type="date" id="effectiveDate" name="effectiveDate" ng-model="data.effectiveDate"
placeholder="Effective Date" ng-required="!hideFutureDate" />
<span class="help-inline" ng-show="submitted && myForm.startDate.$error.required" >A Effective date is required.</span>
<font color="red" >{{dateValidation}}</font>
</div>
</div>
<!--From/To Dates -->
<div ng-hide = "hideRecurrent" >
<div class="row" style="padding-left:15px">
<div class="form-group" ng-class="{ 'has-error' : myForm.startDate.$invalid && myForm.startDate.$dirty && submitted || (myForm.startDate.$invalid && myForm.startDate.$pristine) && submitted }">
<label class="labelColor" ><h5><b>From Date*</b></h5></label><br>
<input style="width:100%" class="item-input-wrapper" type="date" id="startDate" name="startDate" ng-model="data.startDate"
placeholder="From Date" ng-required="!hideRecurrent" />
<span class="help-inline" ng-show="submitted && myForm.startDate.$error.required" >A Start date is required.</span>
<font color="red" >{{dateValidation}}</font>
</div>
<div class="form-group" ng-class="{ 'has-error' : myForm.toDate.$invalid && myForm.toDate.$dirty && submitted || (myForm.toDate.$invalid && myForm.toDate.$pristine) && submitted }">
<label class="labelColor" ><h5><b>To Date*</b></h5></label><br>
<input style="width:100%" class="item-input-wrapper" type="date" id="toDate" name="toDate" ng-model="data.toDate"
placeholder="To Date" ng-required="!hideRecurrent" />
<span class="help-inline" ng-show="submitted && myForm.toDate.$error.required" >An End date is required.</span>
<font color="red" >{{dateValidation}}</font>
</div>
</div>
JS part
$scope.scheduleChange = function(){
if($scope.data.scheduler.name == 'Future Date'){
$scope.hideFutureDate = false;
$scope.hideRecurrent = true;
}
else if($scope.data.scheduler.name == 'Recurrent'){
$scope.hideFutureDate = true;
$scope.hideRecurrent = false;
}
I saw I can use ng-if to resolve this but not sure how.
You can indeed use ng-if to resolve this. Assuming your backend actually can handle blank inputs for things like data.startDate, then you can do:
<input ... ng-if="!hideRecurrent" />
Rather than show/hide the input, ng-if will actually remove it from the page when the condition is not met. And no input on the page means no validation error.