AngularJS Function gets called many times? - javascript

I have a very simple js file for my angular app.
angular.module('Account', ['firebase'])
.value('fbURL', 'https://myURL.firebaseio.com/')
.service('fbRef', function(fbURL) {
return new Firebase(fbURL)
})
.controller('Authorization', function($scope, $firebase, $firebaseObject, fbRef){
var auth = this;
auth.loginEnabled = function() {
alert('false');
return false;
}
auth.loginEmail = function() {
}
});
The auth.loginEnabled function gets called many times (the alert appears many times) when my html loads. Why is this?
In my html
ng-app is declared in my html tag as ng-app="Account"
ng-controller is delcared in my <div class="container"> that wraps an if for angular
ng-if is declared twice, once for a true return and once for a false.
In short, here is my html code: (all your missing is the ng-app code described above)
<div class="container login-container" ng-controller="Authorization as auth">
<div class="row">
<div class="col-sm-12">
<form class="" action="" method="">
<div class="card-container manual-flip">
<div class="card">
<div class="front">
<div class="cover">
<img src="<?php echo $base; ?>assets/img/rotating_card_thumb2.png"/>
</div>
<div class="content" ng-if="auth.loginEnabled()">
<div class="main">
<h3 class="name">Login</h3>
<p class="profession">My Account</p>
<div class="form-group">
<input type="email" ng-model="email" class="form-control" placeholder="E-mail Address">
</div>
<div class="form-group">
<input type="password" ng-model="password" class="form-control" placeholder="Password">
</div>
</div>
<div class="footer">
<button type="submit" class="btn btn-block btn-primary">Login <i class="fa fa-arrow-right"></i></button>
</div>
</div>
<div class="content" ng-if="!auth.loginEnabled()">
<div class="main">
<h3 class="name">Login</h3>
<p class="profession">Temporarily Unavailable</p>
<p class="text-center">We are currently updating our system for a better user experience! Please check back within a few hours.</p>
</div>
<div class="footer">
<i class="fa fa-reply"></i> Return Home
</div>
</div>
<div class="back">
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
I'm wanting to disable the login function all together at certain times, not see if the user is already logged in.

As Orel mentioned, the cause for the repeated alert is simply that your loginEnabled function is called upon every digest cycle. Without going into too much detail, Angular is frequently reevaluating those functions and values bound to the scope to ensure your UI is representing your data accurately.
Thus, it would be preferable to assign the loginEnabled value to a Boolean and query that within the scope:
auth.loginEnabled = false;
$rootScope.$on('myAuthenticationEvent', function () {
auth.loginEnabled = true;
});
The usage of the $rootScope isn't necessary, but serves to demonstrate that some other function in your controller (perhaps a Firebase observer) could be responsible for updating your auth.loginEnabled value. Hope this helps!

The reason is that your controller is called twice, may be because of this
ng-controller="Authorization as auth is mentioned in your view and also while configuring your route you might also include controller there too. like below
url: '/your url',
config: {
templateUrl: 'url',
controllerUrl: 'url',
controller:'Authorization'
}
If that is the case then, change your code to
url: '/your url',
config: {
templateUrl: 'url',
controllerUrl: 'url',
}

Related

Route isn't redirecting me to the correct page. It just shows me the same page but the url changes

I've made a blog template but I having trouble making the routes. When I click on the link, it should redirect me to the article page. Instead it just redirects me to the same page/same exact location.
Here's my code:
<section id="about" class="ts-block" >
<div id="cards_landscape_wrap-2">
<div class="container">
<div class="row">
#foreach($blogs as $blog)
<div class="col-lg-4">
<a href={{route("blogs.show",$blog->slug)}}>
<div class="card-flyer" >
<div class="text-box">
<div class="image-box ">
<img src="{{'/images/blogs/'.$blog->image}}" alt="{{$blog->title}}" class="img-fluid rounded mx-auto d-block" width="100%"/>
</div>
<div class="text-container">
<h6>{{$blog->title}}</h6>
<p style="max-width: 18rem;"class="ts-opacity__50">{{Str::limit($blog->description,100)}}</p>
</div>
<div class="card-footer">
<span class="text-primary font-weight-bold">Read</span>
</div>
</div>
</div>
</a>
</div>
#endforeach
</div>
</div>
</div>
</section>
BlogController :
public function getArticles()
{
return view('blog')->with([
'blogs' => Blog::all(),
]);
}
Routes :
Route::get('/blog/', [App\Http\Controllers\BlogController::class, 'index'])->name('blog');
Route::get('blogs/','App\Http\Controllers\BlogController#getArticles')->name('blogs.show');
Route::get('/admin/blog', 'App\Http\Controllers\BlogController#getBlog')->name('admin.blog');
Route::resource('/blog','App\Http\Controllers\BlogController');
The routes that supposed to be redirecting me to another page is the 2nd one with BlogController#getArticles. The other routes are fine a have no problem.
Can someone kindly show me what I did wrong ?
Well your question is little confusing, because that's the expected result from the code.
You are calling the 'blogs.show' route, which redirects you to the blogs page. If you want to create a seperate page for every article, you can use Dynamic Rounting in laravel.
All you have to do is:
in web.php:
Route::get('blogs/{slug}', 'App\Http\Controllers\BlogController#getArticle')->name('article.show');
and in your controller:
public function getArticles($slug)
{
$article = Blog::where('slug', $slug)->first();
return view('article')->with([
'article' => $article,
]);
}
After that, <a href={{route("article.show",$blog->slug)}}></a> will work.
First, change your route by :
Route::get('/blogs/{slug}','App\Http\Controllers\BlogController#getArticles')->name('blogs.show');
Then, in your function :
public function getArticles($slug)
{
return view('blog')->with([
'blogs' => Blog::firstWhere('slug', $slug);
]);
}

Find div before button

Im trying addClass to wizard-step when button clicked, but still no luck :/
<div class="mt-4">
<div class="wizard-steps">
<div class="wizard-step">
<div class="wizard-step-icon">
<i class="far fa-user"></i>
</div>
</div>
<form class="wizard-content mt-2" id="regForm">
<fieldset>
<div class="form-group row">
<div class="col-lg-4 col-md-6 text-right">
<button type="button" onclick="step0(this);" class="btn">Next</button>
</div>
</div>
</fieldset>
</form>
</div>
JavaScript:
<script>
function step0(element) {
$(element).prev('div').find('.wizard-step').addClass('wizard-step-active');
}
</script>
Can anyone please help me !
prev is used to retrieve a previous sibling element. The .wizard-step you want to target is a child of a sibling to a parent of the button being clicked. As such you need to use closest() instead.
Also note that onclick (and all the other onX attributes) are not good practice and should be avoided. As you're already using jQuery you can attach your event unobtrusively, like this:
jQuery($ => {
$('.btn').on('click', function() {
$(this).closest('.wizard-steps').find('.wizard-step').addClass('wizard-step-active');
});
});
.wizard-step-active { color: #C00; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="mt-4">
<div class="wizard-steps">
<div class="wizard-step">
<div class="wizard-step-icon">
<i class="far fa-user">User icon</i>
</div>
</div>
<form class="wizard-content mt-2" id="regForm">
<fieldset>
<div class="form-group row">
<div class="col-lg-4 col-md-6 text-right">
<button type="button" class="btn">Next</button>
</div>
</div>
</fieldset>
</form>
</div>
Alternatively, instead of calling find() from the shared parent, you could select the form and use prev():
$('.btn').on('click', function() {
$(this).closest('.wizard-content').prev('.wizard-step').addClass('wizard-step-active');
});
Either is fine, it just depends on how your HTML is structured as to which fits best for this use case.
You don't want the div immediately before the button, but the one containing the relevant item(s). So instead of $(element).prev('div') write $('.mt-4').
Your this parameter is referring your button, not your div.
You can do this without Jquery, just using your function like this:
function step0() {
const element = document.getElementsByClassName('wizard-step');
element.classList.add('wizard-step-active');
}
So, you don't need to pass this as a parameter to step0 function.

Angular-js Include js on each state

Hi I have created an angular application and I have created separate controller for each
I want to load each controller when the corresponding state has been reached
I don't to want to load all controller at my index.html
My index.html
<!-- UI Elements-->
<link rel="stylesheet" type="text/css" href="common/resources/UI/css/bootstrap.css">
<script src="common/resources/UI/js/bootstrap.js"></script>
<!-- UI Elements-->
<!--Angular Elements-->
<!--Angular js file from google-->
<script src="common/resources/Angular/Angular/angular.js"></script>
<script src="common/resources/Angular/Angular/angular-route.js"></script>
<script src="common/resources/Angular/Angular/angular-ui-router.js"></script>
<script src="common/resources/Angular/Angular/angular-router-styles.js"></script>
<!--Angular js file from google-->
<!--Angular Modules-->
<script src="common/resources/Angular/Module/module.js"></script>
<!--Angular Modules-->
<!--Angular Route Config-->
<script src="common/resources/Angular/Module/Configuration/rootConfig.js"></script>
<!--Angular Route Config-->
<!--Angular Controller-->
<script src="common/resources/Angular/Controller/ControllerImpl/mainControllerImpl.js"></script>
<script src="common/resources/Angular/Controller/controllers.js"></script>
<!--Angular Controller-->
My RootStatefile
I want to load login.js and use controller loginController when state chnages to /login
/*
Summary : Login Page
Description : Used to show the login page of application
Author : Nithin Prasad
*/
.state('/login', {
url: '/',
controller: 'loginController',
templateUrl: 'module/login/login.html',
data: {
css: [
{
href: 'module/login/css/login.css'
}
],
scripts: [
{
href: 'module/login/js/login.js'
}
]
}
})
I don't want to write all controller implementation in one file and i want it to modularized
Please help
my login.js
var loginController = function ($scope, $log) {
$scope.userName = "nithinprasad59#yahoo.com";
$scope.password = "nithin123";
$scope.userEmail = $scope.userName;
}
smartExpenseApp.controller('loginController', loginController);
my login.html
has a reference to loginController
<div class="container" ng-controller="loginController">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="jumbotron">
<h1>Login</h1>
<form class="form-horizontal" name="loginForm">
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">Email</label>
<div class="col-sm-10">
<input type="email" class="form-control" required id="inputEmail3" placeholder="Email" name="email" ng-model="userEmail">
</div>
</div>
<div ng-show="loginForm.email.$dirty && loginForm.email.$invalid" class="alert alert-danger" role="alert">
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
<span ng-show="loginForm.email.$error.required">Email is required.</span>
<span ng-show="loginForm.email.$error.email">Invalid email address.</span>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">Password</label>
<div class="col-sm-10">
<input type="password" required name="password" class="form-control" id="inputPassword3" placeholder="Password" ng-model="password">
</div>
</div>
<div ng-show="loginForm.password.$dirty && loginForm.password.$invalid" class="alert alert-danger" role="alert">
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
<span ng-show="loginForm.password.$error.required">Password is required.</span>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary">Sign in</button>
</div>
</div>
Hello ! {{userEmail}} Your password is {{password}}
</div>
</div>
</form>
</div>
</div>
</div>
but i am getting following error
LoginControler not found
You want to load the files only when its needed. Such type of loading is called lazy loading. You can add only the primary js and css files in the html and can load the template html and other js files later on when needed.
You can use oclazyload for this.
first do install the dependancy file using bower or npm.
bower install oclazyload
or
npm install oclazyload
then you need to add the module to your application
var smartExpenseApp = angular.module("smartExpenseApp", ["oc.lazyLoad"]);
You are done with that. now inject the dependancy in your controller file that you are added in the index.html.
smartExpenseApp.controller("MyCtrl",['$ocLazyLoad', function($ocLazyLoad) {
//do something here
//now you need your login controller
$ocLazyLoad.load('login.js');
}]);
You can load a file inside a function, switch cases etc.
for more details refer https://oclazyload.readme.io/docs
You need to include your login.js file in index.html, just as you have included others. This is necessary to include all js files, so that they are loaded in sequence. Otherwise your controller function will not be found by system.
If you don't want to load all files at startup on single page load, then you can use angular lazyloading feature, and $controllerProvider.
http://ify.io/lazy-loading-in-angularjs/

angularjs how to set text inside element based on textbox input

My code is:
<div ng-controller="myCtrl">
<div class="row">
<div class="col-md-4 col-sm-3">
<checked-input ng-scope="$eventID"></checked-input>
</div>
<div class="col-md-4 col-sm-3">
<output ng-scope="$postbackOutput">***This is where I want the text typed in the textbox to go***</output>
</div>
<div class="col-md-3 col-sm-3">
<a ng-click="generateURL($eventID)" class="btn-plus">
<span class="glyphicon glyphicon-plus"></span>
</a>
</div>
</div>
</div>
So what I'm trying to do is get that $eventID that's inside the first column div, then pass it as an argument to the function call generateURL() when the link in the <a> tag is clicked in the third column. Inside the controller I have:
app.controller('postbackCtrl', function($scope) {
$scope.generateURL = function(eventID) {
$scope.postbackOutput = eventID;
}
});
But it doesn't seem to be setting the text in the <output> correctly. Could anyone help? I've just started out with angular so it's a bit confusing.
You can just bind the var to the view with handlebar brackets:
<output ng-scope="$postbackOutput">
{{ postbackOutput }}
</output>
Here is a working plunkr

Angular JS binding working only once in the page

I have a page where I do multiple binding to the same object (item, item2, message, messageType)
Though I placed the binding in several part of the page it works only the first time i placed. The objects are filled with ajax calls that return correctly the value (I logged them in the console)
What sounds even strange to me is that the <infomessage> directive has been used in several other places in the app (twice in the same page) and worked perfectly.
Do you have any idea on why these bindings don't work?
I even tried to $watch the objects and they are properly changes but seems that the view use the updated value only the first time
<div class="container" ng-app="MyApp" >
<div class="row" ng-controller="MyCtrl" >
<div class="col-lg-10">
<h3>...</h3>
</div>
<div class="col-lg-10">
<infomessage type="{{messageType}}" message="{{message}}"></infomessage>
</div>
<div class="col-lg-10">
Item: {{item.idbene_ext}} / {{item.id}} / {{item.img}}<br>
Ubicazione: {{item2.id}} {{item2.code}}
</div>
</div>
<div class="row" style="margin-top:20px">
<div class="col-xs-1"></div>
<div class="col-xs-4" ng-class="{'ubiBox':true,'ausilio-enabled':(item!=null),'ausilio-disabled':(item==null), 'boxfocus':(item==null)}">
<div ng-show="item==null">
<div class="number">1</div>
<img src="assets/images/disabled-128.png" width="100" class="img_none"/>
<h4> {{item.idbene_ext}} Select an item</h4>
</div>
<div ng-show="ausilio!=null">
<h4>Item:{{item.idbene_ext}}</h4>
</div>
</div>
<div class="col-xs-2"></div>
<div class="col-xs-4" ng-class="{'ubiBox':true,'ubi-enabled':(item!=null),'ubi-disabled':(item==null),'boxfocus':(item!=null) }">
<div ng-show="item==null">
<div class="number">2</div>
<img src="assets/images/Office-disabled-128.png" width="100" class="img_none"/>
<h4> Select the second item</h4>
</div>
<div ng-show="item!=null">
<h4>Item2 {{item2.code}}</h4>
</div>
</div>
<div class="col-xs-1"></div>
</div>
<div class="row">
<div class="col-lg-10">
<infomessage type="{{messageType}}" message="{{message}}"></infomessage>
</div>
<div class="col-lg-10">
Item: {{item.idbene_ext}} / {{item.id}} / {{item.img}}<br>
Ubicazione: {{item2.id}} {{item2.code}}
</div>
</div>
Here's the angularJS code
MyApp.controller("MyCtrl",function($scope,$http,Config,BarcodeService){
$scope.iditem2=-1
$scope.iditem=-1
$scope.item2=null
$scope.item=null
$scope.message=""
$scope.messageType=""
$scope.$on(BarcodeService.handleitem2,function(){
$scope.message=""
$scope.messageType=""
if($scope.item==null){
$scope.message="select an item before"
$scope.messageType="error"
}
$scope.iditem2=BarcodeService.id
$http
.post(Config.aj,{call:"item2.getitem2",id:$scope.iditem2})
.success(function(data){
$scope.item2=data.payload
})
})
$scope.$watch("item",function(){
console.log("---->",$scope.item)
},true)
$scope.$on(BarcodeService.handleitem,function(){
$scope.message="loading item"
$scope.messageType="info"
$scope.iditem=BarcodeService.id
$http
.post(Config.aj,{call:"item.getArticoloByIdMin",id:BarcodeService.id})
.success(function(data){
$scope.message="item loaded!!"
$scope.item=data.payload
})
})
})
Ok guys, got it!
The problem was lying in the fact that I have two in my application but i placed the ng-controller only on the first one.
This caused all the binding in the second div to fail because they were outside the controller.
I moved the ng-controller in the parent div that contains both and now everything works like a charm.
Thanks anyway to #wachme and #ivarni for taking care of my question.
Happy coding to *

Categories