AngularJS invoke Controller function - angularjs

sorry for the rather basic question but I am really a beginner developing in AngularJS.
So I have a conteoller like this (like explaned here: https://github.com/johnpapa/angular-styleguide):
(function() {
'use strict';
angular
.module('project.management')
.controller('ManagementController', ManagementController);
function ManagementController() {
var vm = this;
vm.getUsersBySearchString= getUsersBySearchString;
////////////
function getUsersBySearchString(searchString) {
alert('get User By searchstring: ' + searchString);
}
};
})();
Now I have a HTML fragment in my template and I really don't know how to invoke function getUsersBySearchString(searchString). I have tried this one:
<div ng-controller="vm">
<form class="well form-search">
<label>Usersuche:</label>
<input type="text" ng-model="term" class="input-medium search-query" placeholder="Username">
<button type="submit" class="btn" ng-click="getUsersBySearchStringgetUsersBySearchString()">Suchen</button>
</form>
<pre ng-model="result">
{{result}}
</pre>
</div>
but I don't know what to put here
<div ng-controller="vm">
and how to invoke the method.
Thanks a lot for help!

<div ng-controller="vm">
That is incorrect. You have no controller named "vm". Your controller is named ManagementController.
The syntax for your use-case is
<div ng-controller="ManagementController as vm">
And to invoke the function, you would use
ng-click="vm.getUsersBySearchString(term)"
Note that the alias you choose in the HTML has no relationship with the alias you chose for thisin the controller code. You might very well use
<div ng-controller="ManagementController as managementCtrl">
and
ng-click="managementCtrl.getUsersBySearchString(term)"

Related

What is the advantage of controller without scope?

Just see the code
var angApp = angular.module('angApp',[]);
angApp.controller('testController', ['$http', function ($http) {
var self = this;
self.name ='Hello';
self.btnClick=function(){
self.name ='Hello! Button Clicked';
}
}]);
<html>
<head>
</head>
<body data-ng-app="angApp" data-ng-controller="testController as model">
<div>
{{model.name}}
</br>
<input type="button" value="Click" data-ng-click="model.btnClick();"/>
</div>
</html>
Now, tell me if we avoid scope and declare controller like this way testController as model then what will be an advantage or is it only syntactic sugar?
Basically, $scope has been removed as of Angular 2. In addition to that, the angular documentation specifically recommends using this instead of $scope.
Take a look at this article for more information: https://johnpapa.net/angularjss-controller-as-and-the-vm-variable/
And also check the accepted answer on this question: 'this' vs $scope in AngularJS controllers
Once advantage I can think about is, if you have nested controllers, for instance
<div ng-controller="myFirstController as ctrl1">
<div ng-controller="mySecondController as ctrl2">
{{ctrl1.someValue}}
</div>
</div>
It is easier and more clear when trying to reference a variable on the parent controller

Angular PDF viewer: How to use

I need to use a pdf viewer on my web app which is in anugularjs. I found Angular PDF viewer and it's ok for me. But I don't know what code insert to use it.
At the moment I've:
in html:
<div ui-content-for="title">
<span class="small"></span>
</div>
<div class="scrollable">
<div class="scrollable-content">
<div class="list-group">
<site-frame style="display:block; height: 100%;">
<pdf-viewer
delegate-handle="my-pdf-container"
url="pdfUrl"
scale="1"
show-toolbar="true"
headers="{ 'x-you-know-whats-awesome': 'EVERYTHING' }">
</pdf-viewer>
<button class="btn btn-default" ng-click="loadNewFile('position/file.pdf')">Load</button>
</site-frame>
</div>
</div>
</div>
in the controller:
'use strict';
var pdfControllerModule = angular.module('pdfControllerModule', ['ServiceOModule']);
pdfControllerModule.controller('pdfController',
['$scope','pdfDelegate', '$routeParams', 'Service_o', function($scope, pdfDelegate ,$routeParams, Service_o) {
$scope.pdfUrl = 'position/file.pdf';
$scope.loadNewFile = function(url) {
pdfDelegate
.$getByHandle('my-pdf-container')
.load(url);
};
}]);
what is incorrect and what code I insert?
Or If you know the correct code to insert in these two file, do you write me? Thanks Help me
I do not see any problem with the code. Just Make sure you have reference to the pdf.js in your main application module.
angular.module('app',['pdf'])
Also the html needs reference to the the pdf.combined and angular-pdf-viewer js files.

ngRepeat not updating after model changed

I'm tring to code a little search input to get data from a database using ngResource.
the data are shown in the page with a ng-repeat, but when i do the search and the $scope has been updated, the view is not updated and show old data.
Here is the code:
main.html (active view)
<div ng-controller="searchCtrl as searchCtrl" layout="column">
<form class="form-inline search-form col-md-offset-1">
<div class="form-group col-md-5">
<label class="sr-only" for="search_location">Location</label> <input
id="search_location" type="search" class="form-control"
ng-Autocomplete ng-model="place" placeholder="Location" />
</div>
<div class="form-group col-md-5">
<label class="sr-only" for="search_tags">Tags</label> <input
style="width: 100%;" id="search_tags" type="search"
class="form-control" id="search_tags" placeholder="Tags">
</div>
<div class="col-md-1">
<md-button class="md-fab md-mini" aria-label="Search" ng-click="searchCtrl.search()"> <md-icon class="md-fab-center"
md-font-icon="glyphicon glyphicon-search" style="color: black;"></md-icon>
</md-button>
</div>
</form>
</div>
<div ng-controller="mainCtrl">
<div ng-repeat="evento in eventi" ng-include="'views/components/event_card.html'" class="col-md-3"></div>
</div>
main.js
'use strict';
app.factory('Eventi', function($resource) {
return $resource('/eventsws/events/:location', {location : '#location'}, {
search: {
method: 'GET',
params: {
'location' : "#location"
},
isArray : true
}
})
});
app.controller('mainCtrl', function($scope, Eventi) {
$scope.eventi = Eventi.query();
});
searchbar.js
'use strict';
app.controller('searchCtrl', function($scope, Eventi) {
$scope.place = null;
this.search = function() {
$scope.eventi = Eventi.search({
'location' : $scope.place
});
}
});
when it start it get all the data from the database and display them correctly, when i try to make a search, the $scope.eventi is updated (i can see the new data in $scope.eventi from the debug) but the view still show the old data and never update.
I've tried to use $scope.$apply at the end of the search function but the result is the same.
Have you any idea why it's not working?
Thanks for your time.
The $scope.eventi you see in the debug is the one in your searchCtrl and not the one from your mainCtrl. To update your mainCtrl $scope.eventi you have to find an other way.
A clean but long solution would be using services to shares variables in your controllers.
To answer the question in comments :
i can see it updated, but the view still show the old data
I guess what's the problem (even if i actually didn't see your code).
Problem
If you bind your var like this :
Service
[...]
service.serviceVar = 1;
return service
[...]
This will create a "1" var with a reference.
Controller
[...]
$scope.myvar = Service.serviceVar;
[...]
This will bind $scope.myvar to the "1" reference.
If you do this in your service or in an other controller :
service.serviceVar = 2;
You will create a new var "2" with a new reference and you will assign this reference to service.serviceVar. Badly all your old references to the old 1 var will not update.
Solution
To avoid that do it like this :
Service
[...]
service.servicevar = {};
service.servicevar.value = 1;
return service
[...]
You create an object with a new reference and assign it to servicevar.
You create a var "1" and assign it to servicevar.value.
Controller
[...]
$scope.myvar = Service.servicevar;
[...]
You assign the servicevar reference to your scope var.
view
{{myvar.value}}
You can use the value by using the property of your var.
Updating the var doing this :
service.servicevar.value = 2;
You will create a new var "2" with a new reference and replace the old reference by this one.
BUT this time you keep all your references to servicevar in your controllers.
I hope i was clear and it answer your question.
EDIT :
Try to never ever use $scope.$apply. It's a really bad practice. If you use that to make something works, you should probably find an other to do that (And it will be a great question for Stacks i guess : "Why do i need $apply to solve my problem XXXXX")
rsnorman15 has a good point about your uses of asynchronous calls. Take a look at his answer too.
Here is one of my old plunker using a service to share properties
Just change:
$scope.eventi = Eventi.search({
'location' : $scope.place
});
to
Eventi.search({
'location' : $scope.place
}, function(eventi) {
$scope.eventi = eventi
});
It's an asynchronous call so it must be assigned in the success handler.
Another issue you are running into is your ng-repeat is not contained within the div that searchCtrl is scoped. Update your HTML so that it is contained like so:
<div ng-controller="searchCtrl as searchCtrl" layout="column">
<form class="form-inline search-form col-md-offset-1">
... form stuff
</form>
<div ng-repeat="evento in eventi" ng-include="'views/components/event_card.html'" class="col-md-3"></div>
</div>

bootstrap-timepicker directive not working inside ng-repeat

Plunker demo
I'm trying to create an arbitrary number of timepicker, when hardcoded they work fine but it stops working when I put them into an ng-repeat. Is there a way to fix this?
I just updated my Plunker with a better solution.
Tiago answered AngularJS ng-repeat finish event with a great directive that will solve your issue without using the $timeout
Here is a copy of the directive:
app.directive('myRepeatDirective', function() {
return function(scope, element, attrs) {
if (scope.$last) {
$('.bootstrap-timepicker').timepicker();
}
};
});
HTML:
<li ng-repeat="list in lists" my-repeat-directive>
{{list.name}}
<div class="input-append">
<input type="text" class="bootstrap-timepicker">
<span class="add-on"><i class="icon-time"></i></span>
</div>
</li>
This is better because if you repeater requires data from an ajax request than your timeout could have to be altered and cause an ugly user experience.
Tiago's method seems to handle it best, in my opinion, you might also want to give him an upvote :)
I solved this using the ng-init because solution provided by Asok was not working for me. I also didn't want to use $scope
AngularCode
angular.module('MyApp', [])
.controller('MyController', MyController);
function MyController($http) {
// your code here...
jd.InitTime = function () {
$('.bootstrap-timepicker').timepicker();
};
};
HTML
<div data-ng-app="MyApp" data-ng-controller="MyController as mc">
<li ng-repeat="list in mc.lists">
{{list.name}}
<div class="input-append">
<input type="text" class="bootstrap-timepicker" ng-init="mc.InitTime();">
<span class="add-on"><i class="icon-time"></i></span>
</div>
</li>
</div>

angular.js view doesn't update

I am updating an object within a resource.save callback like so:
$scope.addProfile = function () {
User.save( { "id": user_id }, $scope.createdProfile, function( savedUser, getResponseHeaders ) {
//$scope.$apply(function () {
$scope.user = savedUser;
console.debug($scope.user); // I doublechecked that this contains the correct data
//});
});
};
Unfortunately the view isn't updating correctly. As you can see I have already tried to wrap the thing in an apply, which results in an error "Error: $digest already in progress". Therefore i commented that bit out again.
The view bit which doesn't update looks like this:
<h1>{{user.name}}</h1>
{{user.location}}
...
The function addProfile is called from a button inside a form like so:
<form name='profileForm' >
<div class="section">
<label class="title">Name <span class="help">(required)</span>
<textarea ng-model="createdProfile.name" ></textarea>
</label>
</div>
<div class="section">
<button class="btn btn-large highlight" ng-disabled="!profileForm.$valid" ng-click="addProfile()">Save</button>
</div>
</form>
Thanks in advance for any help!
You aren't defining your controller in the html.
<ANY ng-controller="{expression}">
...
</ANY>

Resources