I'm new to web development and can't seem to find the answer to this question anywhere. I want my NodeJS API endpoint to be called with every ng-click, not just when the page gets loaded. Here is what I have so far:
HTML:
<button ng-click="myFunction()">Click me!</button>
Angular:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
$http.post("/test").then(function(response) {
$scope.testString = response.data;
});
});
NodeJS
app.get('/test', function(req, res) {
console.log("test get");
});
Is this what you're looking for?
HTML:
<button ng-click="myFunction()">Click me!</button>
Angular:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
$scope.myFunction = function() {
$http.post("/test").then(function(response) {
$scope.testString = response.data;
});
}
});
Related
I am trying to do a file upload using angularjs. But I am getting this error for the past few days and I am unable to resolve:
angular.js:13920 Error: [$injector:unpr] http://errors.angularjs.org/1.5.8/$injector/unpr?p0=fileUploadServiceProvider%20%3C-%20fileUploadService%20%3C-%20appCtrl
at angular.js:38
at angular.js:4511
at Object.d [as get] (angular.js:4664)
at angular.js:4516
at d (angular.js:4664)
at e (angular.js:4688)
at Object.invoke (angular.js:4710)
at S.instance (angular.js:10354)
at p (angular.js:9263)
at g (angular.js:8620)
I only want to read the files uploaded, and store it in the server, and not to link to other URL. I am using Django for my backend. This are my codes:
HTML
<body ng-app="myApp">
<div ng-controller="appCtrl">
<input type="file" id="file" name="files" accept="text/*"
data-url="file" class="upload" ng-model="uploadFile"/>
<label for="file">
<span class="glyphicon glyphicon-open" id="selectFile">
</span>Select a file
</label>
</div>
</body>
<script src="../static/js/services/fileUploadService.js"></script>
<script src="../static/js/controllers/fileUploadController.js"></script>
<script src="../static/js/fileModel.js"></script>
Directives:
var app = angular.module('myApp', [])
app.directive("filesInput", function() {
return {
require: "ngModel",
link: function postLink(scope,elem,attrs,ngModel) {
elem.on("change", function(e) {
var files = elem[0].files;
ngModel.$setViewValue(files);
})
}
}
});
Service
var app = angular.module('myApp', [])
app.factory('fileUploadService', function ($rootScope) {
var _files = [];
var service = {
add: add,
clear: clear,
upload: upload,
}
return service
function add(file){
_files.push(file)
$rootScope.$broadcast('fileAdded', file.files[0].name)
}
function clear(){
_files = []
}
function upload(){
_files.submit();
}
Controller:
var app = angular.module('myApp', [])
app.controller('appCtrl', function ($scope, $rootScope, $http, fileUploadService){
$scope.$watch('uploadFile', function (newVal, oldVal) {
var submitBtn = document.getElementById('submitBtn');
//clear existing files
fileUploadService.clear()
if(newVal == true){
var formdata = new FormData();
$scope.getTheFiles = function ($files) {
angular.forEach($files, function (value, key) {
formdata.append(key, value);
});
};
// NOW UPLOAD THE FILES.
$scope.uploadFile = function () {
var request = {
method: 'POST',
url: file,
data: formdata,
headers: {
'Content-Type': undefined
}
};
// SEND THE FILES.
$http(request)
.success(function (d) {
alert(d);
})
.error(function () {
});
}
}]);
fileUploadService.add(newVal)
fileUploadService.upload()
}
})
By using this:
var app = angular.module('myApp', [])
it creates a new module, so controller, service and directive are registered in a separate module! This results in the injection error as controller cannot inject the service, as it is registered in a different module.
The solution is to only create one module and register all the other components in it, like this:
1st file:
var app = angular.module('myApp', []);
angular.module('myApp').factory('fileUploadService', function ($rootScope) {
...
});
2nd file
angular.module('myApp').controller('appCtrl', function ($scope, $rootScope, $http, fileUploadService){
...
});
3rd file:
angular.module('myApp').directive("filesInput", function() {
...
});
Avoid multiple statements that create the module.
ERRONEOUS
var app = angular.module('myApp', [])
app.directive("filesInput", function() {
//...
});
var app = angular.module('myApp', [])
app.factory('fileUploadService', function ($rootScope) {
//...
}};
var app = angular.module('myApp', [])
app.controller('appCtrl', function ($scope, $rootScope, $http, fileUploadService){
//...
});
The extra angular.module('myApp', []) statements are overwriting existing modules, resulting in the fileUploadService becoming unregistered.
BETTER
angular.module('myApp', [])
angular.module('myApp').directive("filesInput", function() {
//...
});
angular.module('myApp').factory('fileUploadService', function ($rootScope) {
//...
}};
angular.module('myApp').controller('appCtrl', function ($scope, $rootScope, $http, fileUploadService){
//...
});
The statement creating the module must be placed before all the code adding more entities to it.
From the Docs:
Creation versus Retrieval
Beware that using angular.module('myModule', []) will create the module myModule and overwrite any existing module named myModule. Use angular.module('myModule') to retrieve an existing module.
For more information, see
AngularJS Developer Guide - Modules - Creation versus Retrieval
AngularJS angular.module Function API Reference
i want to get all data at once through AJAX($http) request and apply to all controllers
i picked this code from google it shows the i have to make requests for each controller were i can get data in once ajax call and apply objects according to the controlers i have tried factory in angular but it did't work please help me to find out a way where i can get data at once and update all data in controllers
<p>Today's welcome message is:</p>
<h1>{{myWelcome}}</h1>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
$http.get("welcome.htm")
.then(function(response) {
$scope.myWelcome = response.data;
});
});
</script>
thank you.
As per your comment, this will work:
mainApp.controller('ABC',function($rootScope){
$scope.somethingHappened = function(){
$rootScope.$emit('valueChanged',your_data_to_be_passed)
}
})
mainApp.controller('DEF',function($rootScope){
$rootScope.$on('valueChanged',function(event,data){
console.log(data) // you'll see your_data_to_be_passed
})
})
Since, the controllers are not related, you should prefer $rootScope events rather than $scope.$broadcast or $scope.$emit. You can get more details about them on online tutorials
You may use $rootScope instead
<p>Today's welcome message is:</p>
<h1>{{myWelcome}}</h1>
<script>
var app = angular.module('myApp', []);
app.run(function($rootScope){
$http.get("welcome.htm")
.then(function(response) {
$rootScope.myWelcome = response.data;
});
})
app.controller('myCtrl', function($scope, $http) {
// Here watch for scope
$scope.$watch("myWelcome", function(value){
console.log(value)
})
});
</script>
You could use localStorage and use JSON(stringify and parse) methods if the data is not a string, if its object access to properties, if its array access to index.
<script>
var app = angular.module('myApp', []);
app.run(function($rootScope){
$http.get("welcome.htm")
.then(function(response) {
localStorage.setItem('data', JSON.stringify(response));
});
})
app.controller('anotherCtrl', function($scope, $http) {
$scope.myWelcome = JSON.parse(getItem('data'));
/*or you can do this
var full_data = JSON.parse(getItem('data'));
(object)$scope.myWelcome = full_data.[some_property];
(array of objects)$scope.myWelcome = full_data[index].[some_property];
(just array) $scope.myWelcome = full_data[index]
*/
});
</script>
$ctrl.clicker = function(id)
{
$rootScope.$broadcast('idBull', id);
}
When I mouseenter an image the above function gets called. I want to share the id in another controller and broadcast whatever changes where made to this id.
$scope.$on('idBull', function (event, data) {
console.log(data); // 'Data to send'
});
In the other controller I used the code to do a console loge of my id but got no results.
http://jsfiddle.net/87rLob9x/
Check this fiddle hope it helps
html
<html ng-app="myApp">
<div ng-controller='ControllerA'>
<button ng-click='add()'>Add</button
</div>
<div ng-controller='ControllerB'>
{{ increment }}
</div>
</html>
js:
var app = angular.module('myApp', [])
.controller('ControllerA', function($scope) {
$scope.increment = 0;
$scope.add = function() {
$scope.$broadcast('hasIncremented');
}
}).
controller('ControllerB', function($scope) {
$scope.$on('hasIncremented', function(event) {
$scope.increment++;
});
})
Not sure why you are not getting your code to work, maybe the controller with $scope.$on is not created/loaded when the $rootScope.$broadcast is executed?
Another solution is to use a service that you inject into both controllers and use that for communication instead. Example of broadcast solution:
var app = angular.module("app", [])
.controller("ControllerA", function($scope, $rootScope)
{
$scope.clicker = function(id)
{
$rootScope.$broadcast("id changed", id);
}
})
.controller("ControllerB", function($scope)
{
$scope.$on("id changed", function(event, id)
{
// Do whatever you need to do with id
});
});
Example of solution with custom service:
var app = angular.module("app", [])
.factory("customService", function()
{
var callbacks = [];
return {
onIdChange: function(callback)
{
callbacks.push(callback);
},
idChanged: function(id)
{
callbacks.forEach(function(callback)
{
callback(id);
});
}
};
})
.controller("ControllerA", function($scope, customService)
{
$scope.clicker = function(id)
{
customService.idChanged(id);
}
})
.controller("ControllerB", function(customService)
{
customService.onIdChange(function(id)
{
// Do whatever you need to do with id
});
});
I have a view for SidebarController like below -
<a ng-click="reachMe($event);$event.preventDefault()" ng-href="#/app/hello">
Before going to the link I want to call reachMe() to check some changes on page and need to show an alert if any changes made
function SidebarController($rootScope, $scope, $state, $location, SidebarLoader){
$scope.reachMe = function(event){
//here I want to call function isPageChanged() from StaticPageController
//something like this
// if StaticPageController.isPageChanged() return true
// then show alert
// else
// $location.url($href)
}
}
Update 1 :
Not sure about this, But give it a try.
<div ng-app="testApp" ng-controller="ControllerOne">
<button ng-click="methodA();"> Call Another Controller</button>
</div>
<script>
var app = angular.module('testApp', []);
app.controller('ControllerOne', function($scope, $rootScope) {
$scope.reachMe = function() {
var arrayData = [1,2,3];
$rootScope.$emit('callEvent', arrayData);
if($rootScope.isChanged){
// Show Alert
}else{
//Go to route
}
}
});
app.controller('ControllerTwo', function($scope, $rootScope,$state) {
$scope.checkSomethingChanged = function() {
alert("Hello");
$rootScope.isChanged = true;
}
$rootScope.$on('callEvent', function(event, data) {
console.log(data);
$scope.checkSomethingChanged();
});
});
Following method worked for me perfectly :
<div ng-app="testApp" ng-controller="ControllerOne">
<button ng-click="methodA();"> Call Another Controller</button>
</div>
<script>
var app = angular.module('testApp', []);
app.controller('ControllerOne', function($scope, $rootScope) {
$scope.methodA = function() {
var arrayData = [1,2,3];
$rootScope.$emit('callEvent', arrayData);
}
});
app.controller('ControllerTwo', function($scope, $rootScope) {
$scope.reachMe = function() {
alert("Hello");
}
$rootScope.$on('callEvent', function(event, data) {
console.log(data);
$scope.reachMe();
});
});
</script>
A controller is not the right concept for sharing functionality. Use a Factory or Service for that.
var logicFactory = function () {
return {
methodA: function () {
},
methodB: function()
{
}
};
}
You can then inject that factory into each controller where it is needed like:
var ControllerA = function ($scope,logicFactory) {
$scope.logic = logicFactory;
}
ControllerA.$inject = ['$scope', 'logicFactory'];
Another option is to use the broadcast/emit Patern. But I would use that only where really necessary:
Usage of $broadcast(), $emit() And $on() in AngularJS
I created 2 HTML pages as Angular modules.
var app = angular.module("oneApp", []);
app
.controller(
'controller-one',
[
'$scope',
'$http',
function($scope, $http) {...functions..}]);
Both how different controllor files. But now I need this two controllers to exchange some data.
I found this related question in SO : related Thread
When trying to changing on controllor to that..
var app = angular.module("oneApp", ['twoAoo']);
.. I get an injection error. I think that's because both file are not related.
How to accomplish to exchange data correctly?
To share data between two modules, you need to use a service.
var otherApp = angular.module('otherApp', []);
otherApp.factory('myService', function() {
var myService = {
someData: ''
};
return myService;
});
otherApp.controller('otherCtrl', function($scope, myService) {
$scope.shared = myService;
});
var app = angular.module('myApp', ['otherApp']);
app.controller('myCtrl', function($scope, myService) {
$scope.shared = myService;
});
This article can help you further: https://thinkster.io/a-better-way-to-learn-angularjs/services
As #Penman said, you should use a service (here, I used a factory).
A very simple use case is to have a service with a method that log something. Then we use this service from 2 different modules.
Here's how I did it :
index.html
<body>
<div ng-app="appOne">
<div ng-controller="appOneCtrl">
{{ name }} <button ng-click="log()">Log</button>
</div>
<div ng-app="appTwo">
<div ng-controller="appTwoCtrl">
{{ name }} <button ng-click="log()">Log</button>
</div>
</div>
</div>
</body>
script.js
// APP 1
const app1 = angular.module('appOne', ['appTwo']);
app1.controller('appOneCtrl', function($scope, $log, sharedFactory) {
$scope.name = 'App 1, ctrl 1';
$scope.log = () => {
$log.info('Click on log button from appOne');
sharedFactory.logMeSomething();
};
});
// -----------------------------------------
// APP 2
const app2 = angular.module('appTwo', []);
app2.controller('appTwoCtrl', function($scope, $log, sharedFactory) {
$scope.name = 'App 2, ctrl 2';
$scope.log = () => {
$log.info('Click on log button from appTwo');
sharedFactory.logMeSomething();
};
});
app2.factory('sharedFactory', function($log) {
return {
logMeSomething: () => {
$log.debug('Something logged from sharedFactory !');
}
};
});
Clicking on "Log 1" button displays :
Click on log button from appOne
Something logged from sharedFactory !
Clicking on "Log 2" button displays :
Click on log button from appTwo
Something logged from sharedFactory !
Here's a working Plunkr of my solution :
https://plnkr.co/edit/sgOKkh0eh0URPGIP9dZY?p=preview