Angular JS lazy loading not working - angularjs

I have an application in angularjs where each controller is in written in different JS files.
I need to call those files only on routechange event. For now I am successful in getting the appropriate controller file, but for some reason its throwing error:
Error: [ng:areq] Argument 'ApplicantsController' is not a function, got undefined
http://errors.angularjs.org/1.2.25/ng/areq?p0=ApplicantsController&p1=not%20a%20function%2C%20got%20undefined
minErr/<#http://localhost/talentojo/app/js/angularjs/angular.js:78:5
assertArg#http://localhost/talentojo/app/js/angularjs/angular.js:1509:5
assertArgFn#http://localhost/talentojo/app/js/angularjs/angular.js:1520:76
$ControllerProvider/this.$get</<#http://localhost/talentojo/app/js/angularjs/angular.js:7278:9
nodeLinkFn/<#http://localhost/talentojo/app/js/angularjs/angular.js:6670:13
forEach#http://localhost/talentojo/app/js/angularjs/angular.js:332:11
nodeLinkFn#http://localhost/talentojo/app/js/angularjs/angular.js:6657:11
compositeLinkFn#http://localhost/talentojo/app/js/angularjs/angular.js:6105:13
publicLinkFn#http://localhost/talentojo/app/js/angularjs/angular.js:6001:30
z/<.link#https://code.angularjs.org/1.2.25/angular-route.min.js:7:388
nodeLinkFn#http://localhost/talentojo/app/js/angularjs/angular.js:6712:1
compositeLinkFn#http://localhost/talentojo/app/js/angularjs/angular.js:6105:13
publicLinkFn#http://localhost/talentojo/app/js/angularjs/angular.js:6001:30
createBoundTranscludeFn/boundTranscludeFn#http://localhost/talentojo/app/js/angularjs/angular.js:6125:1
controllersBoundTransclude#http://localhost/talentojo/app/js/angularjs/angular.js:6732:11
v#https://code.angularjs.org/1.2.25/angular-route.min.js:6:355
$RootScopeProvider/this.$get</Scope.prototype.$broadcast#http://localhost/talentojo/app/js/angularjs/angular.js:12980:15
l/<#https://code.angularjs.org/1.2.25/angular-route.min.js:11:127
qFactory/defer/deferred.promise.then/wrappedCallback#http://localhost/talentojo/app/js/angularjs/angular.js:11572:15
qFactory/defer/deferred.promise.then/wrappedCallback#http://localhost/talentojo/app/js/angularjs/angular.js:11572:15
qFactory/ref/<.then/<#http://localhost/talentojo/app/js/angularjs/angular.js:11658:11
$RootScopeProvider/this.$get</Scope.prototype.$eval#http://localhost/talentojo/app/js/angularjs/angular.js:12701:9
$RootScopeProvider/this.$get</Scope.prototype.$digest#http://localhost/talentojo/app/js/angularjs/angular.js:12513:15
$RootScopeProvider/this.$get</Scope.prototype.$apply#http://localhost/talentojo/app/js/angularjs/angular.js:12805:13
done#http://localhost/talentojo/app/js/angularjs/angular.js:8378:34
completeRequest#http://localhost/talentojo/app/js/angularjs/angular.js:8592:7
createHttpBackend/</xhr.onreadystatechange#http://localhost/talentojo/app/js/angularjs/angular.js:8535:1
My code:
HTML
<body>
<!-- Header Starts -->
<div ng-include="'assets/defaults/header.html'"></div>
<!-- Header Ends -->
<ul>
<li>
Home
</li>
<li>
Applicants
</li>
</ul>
<div ng-view></div>
<!-- Footer Starts -->
<div ng-include="'assets/defaults/footer.html'"></div>
<!-- Footer Ends -->
</body>
Route:
var app = angular.module('TOJO',['ngRoute']);
app.config(function($routeProvider, $locationProvider) {
$routeProvider.when('/', {
templateUrl : 'assets/home.html',
controller : 'HomeController'
}).when('/applicants', {
templateUrl : 'assets/applicants/list.html',
scriptUrl : 'assets/applicants/applicants.js'
});
}).
run(function($rootScope, $location) {
$rootScope.$on( "$routeChangeStart", function(event, next, current) {
if(next.scriptUrl !== undefined)
loadScript(next.scriptUrl);
});
});
app.controller('HomeController', function($scope) {
$scope.message = 'Look! I am home page.';
});
var loadScript = function(url, type, charset) {
if (type===undefined) type = 'text/javascript';
if (url) {
var script = document.querySelector("script[src*='"+url+"']");
if (!script) {
var heads = document.getElementsByTagName("head");
if (heads && heads.length) {
var head = heads[0];
if (head) {
script = document.createElement('script');
script.setAttribute('src', url);
script.setAttribute('type', type);
if (charset) script.setAttribute('charset', charset);
head.appendChild(script);
}
}
}
return script;
}
};
And the file applicants.js which is getting called on route change:
app.controller('ApplicantsController',['$scope', function($scope) {
$scope.message = 'Look! I am home page.';
}
]);
list.html:
<div ng-controller="ApplicantsController">{{message}}</div>

Had you already a look, into: https://docs.angularjs.org/api/ngRoute/provider/$routeProvider resolve event?
"If any of these dependencies are promises, the router will wait for them all to be resolved or one to be rejected before the controller is instantiated." -> Maybe you can insert your script here into the body / head tag and return a promise.
I use this to include stylesheets e.g.
resolve: {
style: function () {
angular.element('head').append('<link href="*.css" rel="stylesheet">');
}
}

So finally I found the solution:
I used resolve, to add script in my document dynamically. So my route:
var app = angular.module('TOJO',['ngRoute']).service('HttpTojoService', Service);
app.config(function($routeProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) {
app.controllerProvider = $controllerProvider;
app.compileProvider = $compileProvider;
app.routeProvider = $routeProvider;
app.filterProvider = $filterProvider;
app.provide = $provide;
$routeProvider.when('/', {
templateUrl : 'assets/home.html',
controller : 'HomeController'
}).when('/applicants', {
templateUrl : 'assets/applicants/list.html',
controller : 'ApplicantsController',
resolve:{deps:function($q, $rootScope){
return routeResolver($q.defer(),['assets/applicants/applicants.js'],$rootScope);
}}
}).when('/jobs', {
templateUrl : 'assets/jobs/list.html',
controller : 'JobsController',
resolve:{deps:function($q, $rootScope){
return routeResolver($q.defer(),['assets/jobs/jobs.js'],$rootScope);
}}
});
});
function routeResolver(deferred,dependencies,$rootScope){
$script(dependencies, function()
{
$rootScope.$apply(function()
{
deferred.resolve();
});
});
return deferred.promise;
}
and my controller:
app.controllerProvider.register('ApplicantsController',['$scope', 'HttpTojoService', function($scope, HttpTojoService) {
$scope.message = 'Look! I am applicants page.';
}
]);
And also you'll also need scripts.js

Related

Error: [$controller:ctrlreg] The controller with the name 'CounterController' is not registered.

I see this error when I press F12 in chrome.
There seems to be no problems.
My html code
<ul class="dropdown-menu" role="menu" ng-controller="CounterController">
<li ng-repeat="item in messages">{{item.name}}</li>
</ul>
Here is my js file. Any idea why?
The version of angualr I am using is 1.6.1
angular controller code
angular
.module('myApp.counter_controller', [])
.controller('CounterController', ['$scope', '$filter', function($scope, $filter) {
'use strict';
$scope.messages = [{
name : 'ENG',
read : false
}, {
name : 'JPN',
read : false
}, {
name : 'CHI',
read : false
}, ];
$scope.setRead = function(item, $event) {
$event.preventDefault();
$event.stopPropagation();
item.read = true;
};
$scope.setUnread = function(item, $event) {
$event.preventDefault();
$event.stopPropagation();
item.read = false;
};
$scope.setReadAll = function($event) {
$event.preventDefault();
$event.stopPropagation();
angular.forEach($scope.messages, function(item) {
item.read = true;
});
};
$scope.unseenCount = $filter('filter')($scope.messages, {
read: false
}).length;
$scope.$watch('messages', function(messages) {
$scope.unseenCount = $filter('filter')(messages, {
read: false
}).length;
}, true);
}]);
You may have done some file arranging problem.
please see code it is working fine :code link
output:Main Output
you may need to wrap them in an anonymous function like so
(function(){
var myApp = angular.module('myAPP', ['ngRoute']);
storehubs.controller('welcome',['$scope',function($scope){
$scope.pageClass="welcome_page";
}]);
})();
Also your html should include ng-app="myApp" and your links to angular.min.js and yourapp.js files need to be in the head tag of your html.
Look at some docs https://docs.angularjs.org/guide/controller

Why my service does not share data between controllers?

I built a factory to get Data from the Database and pass to all controllers in my application like this:
(function () {
angular.module('appContacts')
.factory('dataService', ['$http', dataService]);
function dataService($http) {
return {
getCurrentOrganization: getCurrentOrganization,
};
function getCurrentOrganization(id) {
return $http({
method: 'GET',
url: '/api/organization/' + id + '/contacts'
})
}
}
})();
And I have a view like this:
<div ng-app="myapp">
<div ng-controller="contactController">
<a ui-sref="organization({Id: organization.id})" ng-click="vm.setCurrentOrganization(organization)"> {{organization.organizationName }}</a>
</div>
</div>
That link redirect from a view the view contactsView.html to a detail view organizationDetail.html managed by a second controller:
....
.state("home", {
url: "/",
templateUrl: "views/contactsView.html",
controller: "contactsController",
controllerAs: "vm"
})
.state("organization", {
url: "/organization/:Id",
templateUrl: "views/organizationDetail.html",
params: { Id: null },
controller: "organizationsController",
controllerAs: "vm"
})
...
My problem is that I get the data, I see in the console, but when the new URL comes into place, the Data is gone and the view is shown empty.
How could I use the data produced in the factory in the second Controller?
EDIT:
Here are the Controllers:
//organizationsController.js
(function () {
"use strict";
angular.module('appContacts')
.controller('organizationsController', function organizationsController(dataService) {
var vm = this;
vm.setCurrentOrganization = function (organization) {
vm.theOrganization = organization;
vm.visible = true;
dataService.getCurrentOrganization(vm.theOrganization.id).then(function (result) {
vm.organizationData = result.data;
}, function () {
vm.errorMessage = "Failed to load" + Error;
});
}
});
})();
And the contactsController:
//contactsController.js
(function () {
"use strict";
angular.module('appContacts')
.controller('contactsController', function contactsController(dataService) {
var vm = this;
vm.visible = false;
activate();
function activate() {
dataService.getAllContacts().then(function (result) {
vm.allcontacts = result.data;
}, function () {
vm.errorMessage = "Failed to load" + Error;
});
dataService.getAllOrganizations().then(function (result) {
vm.organizations = result.data;
}, function () {
vm.errorMessage = "Failed to load" + Error;
});
}
});
})();
The problem is that I click the llink in the view A (contactsView.html/ContactsViewController) and I should end in the VIEW B (OrganizationDetails.html/organizationController), using the Data fetch in the service.
You are doing it wrong here
<div ng-app="myapp">
<div ng-controller="contactController">
<a ui-sref="organization({Id: organization.id})" ng-click="vm.setCurrentOrganization(organization)"> {{organization.organizationName }}</a>
</div>
</div>
Your contactController does not have the function setCurrentOrganization. Instead its in another controller. you can remove the code ng-click="vm.setCurrentOrganization(organization)" from the HTML. and read the id using $stateParams in the organizationsController. After getting the id, use it call the service as below:
dataService.getCurrentOrganization(id).then(function (result) {
vm.organizationData = result.data;
}, function () {
vm.errorMessage = "Failed to load" + Error;
});

ui-view do not bind to controler

I using ui-router for the first time. I've check some tutorial, but nerver been able to make my project work.
I have a page with a controler, my file home.htm get request is complete but the ui-view do not display it.
index.htm
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.min.js"></script>
<script ng-include="'http://192.168.0.110/home.htm'"></script>
angular
.module('app', [
'ui.router'
])
.config(['$urlRouterProvider', '$stateProvider', function($urlRouterProvider, $stateProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('/', {
url:"/",
templateUrl: 'http://192.168.0.110/home.htm',
controller:'temperatureCTRL'
})
}])
.controller('temperatureCTRL', ["$scope", "$interval", "ArduinoService", function($scope, $interval, service) {
var autoRefresh;
$scope.channels = [];
function startRefresh(){
autoRefresh = $interval(function() {
updateAjax();
}, 5000);
}
function updateAjax() {
service.getChannels(function(err, result) {
if (err) {
return alert(err);
}
// puis les mets dans le scope
$scope.channels = result.channels;
})
};
$scope.init = function() { //on load page first get data
updateAjax();
startRefresh()
}
$scope.switchChannel = function($scope, channel) { // change name function
var switchCh = {canal : $scope.canal, status : $scope.status}
service.switchChannel(switchCh, function() {
});
updateAjax();
};
$scope.channelsClk = function($scope, channel) {
var chanObj = {setPoint : $scope.setPoint, name : $scope.name, canal : $scope.canal
};
service.putChannels(chanObj, function() {
});
}
$scope.stopRefresh = function() { //ng-mousedown
$interval.cancel(autoRefresh);
};
$scope.restartRefresh = function() {
startRefresh();
console.log('lost focus');
};
$scope.$on('$destroy', function() {
// Make sure that the interval is destroyed too
$scope.restartRefresh();
});
}])
.service('ArduinoService', ['$http', function($http) {
return {
getChannels: function(cb) {
$http.get('http://192.168.0.110/ajax_inputs')
.success(function(result) {
cb(null, result);
});
},
switchChannel: function(switchCh, cb) {
$http.put('http://192.168.0.110/switch', {
switchCh
})
.success(function(result) {
cb(null, true);
});
},
putChannels: function(channels, cb) {
$http.put('http://192.168.0.110/channels', {
channels
})
.success(function(result) {
cb(null, true);
});
}
};
}])
now home.htm
<!DOCTYPE html><!-- directive de repeat sur les données de vue channels -->
<div class="IO_box" ng-repeat="channel in channels">
<h2>{{channel.canal}}</h2>
<button type="button" ng-click="switchChannel(channel, channel.canal)" ng-model="channel.status"> {{channel.status}} </button>
<h2>
<form> name:<br>
<input type="text" name="Name" size="6" autocomplete="off" ng-model="channel.name" ng-focus="stopRefresh()" ng-blur="restartRefresh()">
<button ng-click="channelsClk(channel, channel.name)">change</button>
</form>
</h2>
<br>
<h4><span class="Ainput" >{{channel.temperature}}ºC</span></h4>
<h2>Setpoint
<input type="number" name="setpoint" ng-model="channel.setPoint" ng-focus="stopRefresh()" ng-blur="restartRefresh()"
min="5" max="30" step="0.5" size="1"> ºC <br />
<button ng-click="channelsClk(channel, channel.setPoint)">ok</button>
</h2>
<h5>state:
<span class="permRun">{{channel.permRun}}</span>
</h5>
<h5>
<span class="AoutputChannel">{{channel.percent_out}}%</span>
</h5>
There's no need to put the domain in the templateUrl. You're also trying to fetch it from your internal ip address but I think really you want to hit localhost which can just be written as http://localhost:PORT where PORT is whatever port your server is running on.
So your state definition should be:
$stateProvider
.state('/', {
url:"/",
templateUrl: './home.htm', //assumes this template is in the same dir as the state definition file
controller:'temperatureCTRL'
});
Also, if you want to display other templates you need to add <div ui-view></div> to your home.htm file so that ui-router knows where to display any nested templates (as Simon H commented there is no need for the ng-include).
Not related to ui-router but you shouldn't need to hardcode the domain name into your $http requests. Angular will use the current domain if you just write e.g. '/ajax_inputs' (which should be fine in your case because you are attempting to hit localhost). If you want to hit another domain then put that in a variable that can be easily changed.
getChannels: function(cb) {
$http.get('/ajax_inputs')
.then(function(result) { // .then with callback for error handling (success and error methods are being deprecated)
cb(null, result);
}, function(error) {
// handle error here
});
}

Nothing happens when Angular Href is clicked

I am using Angular Routing with a webapi 2 controller.
Although the default path loads with the correct data, when I click on an item in a list containing a link to a details page, no data is loaded.
The browser shows what I believe to be the correct url (http://localhost:xxxxx/#/details/2) but the DetailsController script file is not called and no method on the webapi2 controller is called.
Here is my main page :
<div class="jumbotron">
<h1>Movies Example</h1>
</div>
#section scripts {
<script src="~/Scripts/angular.js"></script>
<script src="~/Scripts/angular-route.js"></script>
<script src="~/Client/Scripts/atTheMovies.js"></script>
<script src="~/Client/Scripts/ListController.js"></script>
<script src="~/Client/Scripts/DetailsController.js"></script>
}
<div ng-app="atTheMovies">
<ng-view></ng-view>
</div>
Here is the list partial :
<div ng-controller="ListController as ctrl">
<h1>{{ctrl.message}}</h1>
<h2>There are {{ctrl.movies.length}} Movies in the Database</h2>
<table>
<tr ng-repeat="movie in ctrl.movies">
<td>{{movie.Title}}</td>
<td>
<a ng-href="/#/details/{{movie.Id}}" >Details</a>
</td>
</tr>
</table>
</div>
Here is the details partial:
<div ng-controller="DetailsController as ctrl2">
<h2>ctrl2.message</h2>
<h2>{{movie.Title}}</h2>
<div>
Released in {{movie.ReleaseYear}}
</div>
<div>
{{movie.Runtime}} minutes long.
</div>
</div>
Here is the javascript file to create the angular app:
(function () {
var app = angular.module("atTheMovies", ["ngRoute"]);
var config = function ($routeProvider) {
$routeProvider
.when("/list", { templateUrl: "/client/views/list.html" })
.when("/details/:id", { templatUrl: "/client/views/details.html" })
.otherwise(
{ redirectTo: "/list" });
};
app.config(config);
}());
Here is the javascript file to create the list controller:
(function (app) {
app.controller("ListController", ['$http', function ($http) {
var ctrl = this;
ctrl.message = "Hello World!";
ctrl.movies = [];
$http.get("/api/movie")
.success(function (data) {
ctrl.movies = data;
})
.error(function(status){
ctrl.message = status;
});
}])
}(angular.module("atTheMovies")));
Here is the javascript file to create the details controller:
(function (app) {
app.controller("DetailsController", ['$routeParams', '$http', function ($routeParams, $http) {
var ctrl2 = this;
ctrl2.message = "";
ctrl2.movie = {};
var id = $routeParams.id;
$http.get("/api/movie/" + id)
.success(function(data){
ctrl2.movie = data;
}).error(function (status) {
ctrl2.message = status;
});
}])
}(angular.module("atTheMovies")));
Finally here is the webapi2 controller
public class MovieController : ApiController
{
private MovieDb db = new MovieDb();
// GET: api/Movie
public IQueryable<Movie> GetMovie()
{
return db.Movies;
}
// GET: api/Movie/5
[ResponseType(typeof(Movie))]
public IHttpActionResult GetMovie(int id)
{
Movie movie = db.Movies.Find(id);
if (movie == null)
{
return NotFound();
}
return Ok(movie);
}
You have a typo in your route config i.e. templatUrl
.when("/details/:id", { templatUrl: "/client/views/details.html" })
should be
.when("/details/:id", { templateUrl: "/client/views/details.html" })

angularjs share data config between controllers

I'm wondering what could be a good way to share directive
between controller.
I've got ie two directives to use in different controller
with different configuration the first think I thought of
using like:
//html
<body data-ng-controller="MainCtrl">
<div class="container">
<div data-ui-view></div>
</div>
</body>
//js
.controller('MainCtrl', function ($scope,$upload) {
/*File upload config*/
$scope.onFileSelect = function($files) {
for (var i = 0; i < $files.length; i++) {
var file = $files[i];
$scope.upload = $upload.upload({
url: 'server/upload/url',
method: 'POST',
data: {myObj: $scope.myModelObj},
file: file,
}).progress(function(evt) {
console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
}).success(function(data, status, headers, config) {
console.log(data);
});
}
};
/* Datepicker config */
$scope.showWeeks = true;
$scope.minDate = new Date();
$scope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened = true;
};
$scope.dateOptions = {
'year-format': "'yy'",
'starting-day': 1
};
$scope.format = 'MMM d, yyyy';
})
.controller('IndexCtrl', function ($scope) {
})
doing so I can use all the functions in my children controller
but I don't like very much because of collision problems.
Since you cannot use a service (you can't use $scope in a service) the other alternatives could be make an other directive or put the code in a run block
but it's quite the same using a parent controller so
what do you think about ?
UPDATE
what do you think about this approach ?
//outside of angular stauff
function MyTest(){
this.testScope = function(){
console.log('It works');
}
}
//inside a controller
$scope.ns = new MyTest();
//in the view
<p ng-click="ns.testScope()">ppp</p>
RIUPDATE
this seems the best option :)
MyTest.call($scope);
Consider the method described by this post: Extending AngularJS Controllers Using the Mixin Pattern
Instead of copying your methods out of a service, create a base controller that contains those methods, and then call extend on your derived controllers to mix them in. The example from the post:
function AnimalController($scope, vocalization, color, runSpeed) {
var _this = this;
// Mixin instance properties.
this.vocalization = vocalization;
this.runSpeed = runSpeed;
// Mixin instance methods.
this.vocalize = function () {
console.log(this.vocalization);
};
// Mixin scope properties.
$scope.color = color;
// Mixin scope methods.
$scope.run = function(){
console.log("run speed: " + _this.runSpeed );
};
}
Now we can mixin AnimalController into DogController:
function DogController($scope) {
var _this = this;
// Mixin Animal functionality into Dog.
angular.extend(this, new AnimalController($scope, 'BARK BARK!', 'solid black', '35mph'));
$scope.bark = function () {
_this.vocalize(); // inherited from mixin.
}
}
And then use DogController in our template:
<section ng-controller="DogController">
<p>Dog</p>
<!-- Scope property mixin, displays: 'color: solid black' -->
<p ng-bind-template="color: {{ color }}"></p>
<!-- Calls an instance method mixin, outputs: 'BARK BARK!' -->
<button class="btn" ng-click="bark()">Bark Dog</button>
<!-- Scope method mixin, outputs: 'run speed: 35mph' -->
<button class="btn" ng-click="run()">Run Dog</button>
</section>
The controllers in this example are all in the global space and are included in the markup as follows.
<script type="text/javascript" src="lib/jquery.js"></script>
<script type="text/javascript" src="lib/angular.js"></script>
<script type="text/javascript" src="app/controllers/animal-controller.js"></script>
<script type="text/javascript" src="app/controllers/dog-controller.js"></script>
<script type="text/javascript" src="app/controllers/cat-controller.js"></script>
<script type="text/javascript" src="app/app.js"></script>
I haven't tested it, but I don't see why the following wouldn't work:
var myApp = angular.module('myApp', [])
.controller('AnimalController', ['$scope', 'vocalization', 'color', 'runSpeed', function ($scope, vocalization, color, runSpeed) { /* controller code here */}]);
.controller('DogController', ['$scope', '$controller', function($scope, $controller) {
var _this = this;
// Mixin Animal functionality into Dog.
angular.extend(this, $controller('AnimalController', {
$scope: scope,
vocalization: 'BARK BARK!',
color: 'solid black',
runSpeed:'35mph'
}));
$scope.bark = function () {
_this.vocalize(); // inherited from mixin.
}
}]);
see: docs for $controller service
What you want is terrible.
You wouldn't want your controllers to know anything about each other, let alone, one having access to the function of the other. You can just use a Service to achieve that. As for using directives, not sure what exactly you want to happen.
As for your second thing, you can as easily do this
.service('MyTestService', function(){
return {
testScope: function(){
console.log('It works');
}
};
})
.controller('MyController', ['$scope', 'MyTestService', function($scope, MyTestService){
$scope.testScope = MyTestService.testScope;
}])
and in your view:
<p ng-click="testScope()">ppp</p>
I ended up with:
//service
.service('PostUploader',function($upload){
var that = this;
var fileReaderSupported = window.FileReader !== null;
this.notify = null;
this.success = null;
this.showAlert = false;
this.avatar = '';
this.onFileSelect = function($files) {
var $file = $files[0];
var filename = $file.name;
this.avatar = filename;
var isImage = /\.(jpeg|jpg|gif|png)$/i.test(filename);
if(!isImage){
this.showAlert = true;
return;
}
this.showAlert = false;
if (fileReaderSupported && $file.type.indexOf('image') > -1) {
var fileReader = new FileReader();
fileReader.readAsDataURL($file);
fileReader.onload = that.notify;
}
$upload.upload({
url :'/api/post/upload',
method: 'POST',
headers: {'x-ng-file-upload': 'nodeblog'},
data :null,
file: $file,
fileFormDataName: 'avatar'
})
.success(that.success)
.progress(function(evt) {
})
.error(function(data, status, headers, config) {
throw new Error('Upload error status: '+status);
})
};
this.closeAlert = function() {
this.showAlert = false;
};
})
//controller
/* Uploader post */
$scope.dataUrl = null;
$scope.avatar = PostUploader.avatar;
$scope.showAlert = PostUploader.showAlert;
$scope.onFileSelect = PostUploader.onFileSelect;
$scope.closeAlert = PostUploader.closeAlert;
PostUploader.notify = function(e){
$timeout(function() {
$scope.dataUrl = e.target.result;
});
};
PostUploader.success = function(data, status, headers, config) {
$timeout(function() {
$scope.post.avatar = data.url;
});
}
$scope.$watch('avatar',function(newVal, oldVal){
if(newVal) {
$scope.avatar = newVal;
}
});
$scope.$watch('showAlert',function(newVal, oldVal){
$scope.showAlert = newVal;
$scope.dataUrl = null;
});
I did so because I've to do the same thing in create post and edit post but all in all
I've got quite the same repeated code ! :)
The only good thing is the code has got less logic.
obvious but brilliant solution (may be)
(function(window, angular, undefined) {
'use strict';
angular.module('ctrl.parent', [])
.run(function ($rootScope) {
$rootScope.test = 'My test'
$rootScope.myTest = function(){
alert('It works');
}
});
})(window, angular);
angular.module('app',['ctrl.parent'])
.controller('ChildCtrl', function($scope){
});
It's easy and clean and don't see any drawback(it's not global)
UPDATE
'use strict';
(function(window, angular, undefined) {
'use strict';
angular.module('ctrl.parent', [])
.controller('ParentController',function (scope) {
scope.vocalization = '';
scope.vocalize = function () {
console.log(scope.vocalization);
};
});
})(window, angular);
angular.module('app',['ctrl.parent'])
.controller('ChildCtrl', function($scope,$controller){
angular.extend($scope, new $controller('ParentController', {scope:$scope}));
$scope.vocalization = 'CIP CIP';
});
just a little neater and it works CIP CIP :)

Resources