I'm trying to get the text defined in our translations.js file in order to pass it to an angular-bootstrap alert as its text. I've injected the $translate service into the controller and am using the $translate service like so:
$translate('TXT_ALERT_MSG').then(function (translation) {
$log.debug( translation );
});
but it breakes angular and states the following error message:
TypeError: object is not a function
This is thrown on the very first line of the code above. I wrapped it in a promise to make sure i only print the value upon successfully retrieving the translation. I also tried assigning the value to a variable but this throws the same error:
function getTranslation() {
var msg = $translate('TXT_ALERT_MSG');
$log.debug(msg);
}
getTranslation();
This is most likely something simple so what is it?
Thanks
EDIT
How I inject the translate module into the app:
angular.module('MainApp',['pascalprecht.translate']);
and how it's configured:
angular.module('MainApp').config(['$translateProvider', 'ConfigProvider', function ($translateProvider, ConfigProvider) {
var config = ConfigProvider.$get();
var rootUrl = config.get('ourRootUrl');
$translateProvider.translations('en', {
// all our translations e.g.
TIMED_OUT_BUTTON: 'Return to Dashboard'
$translateProvider.preferredLanguage('en');
}]);
Try to get the translations by translate filter
$filter('translate')('TIMED_OUT_BUTTON')
Related
I have the following file: classAModel.js with the following code:
class classAModel{
constructor(model) {
'ngInject';
if (!model) return {};
this.id = model.id;
this.name = model.name;
this.displayName = model.displayName;
}
}
export default classAModel;
This code is defined as a factory in another file: module.js:
import classAModelfrom './classAModel'
module.factory('ClassAModel', ClassAModel);
This code works perfectly when not in a testing context. It works using Webpack to create a bundle that is loaded and runs. So far so good. Now, the question is how do I test this class. Before I changed my code to es6 style, it used be a function and it worked. The test first loads the bundle, but when I try to inject the factory (again, same as before), I get an error: Unknown provider: modelProvider <- model <- classAModel. I can understand why he thinks there is a problem, but I can't understand how to fix it.
Moreover, I'm wondering if this is the correct way to work with the factory rather then create a factory method inside the class, that gets the model, and then create my object.
Thanks
Based on the information you've provided, here's a simple test case for testing your factory. Hope this is what you're looking for.
import classAModel from './classAModel'
let classAInstance;
describe('classAModel', function() {
beforeEach(function() {
modelInstance = new Model();
classAInstance = new classAModel(modelInstance);
});
it('should have id provided by model', () => {
expect(classAInstance.id).toBe(modelInstance.id);
});
});
I want to update my json object with PUT method using the update function in angularjs but after using the update method I get the error of :
angular.js:14324 TypeError: menuFactory.getDishes(...).update is not a function
at b.$scope.submitComment (controllers.js:104)
at fn (eval at compile (angular.js:15152), <anonymous>:4:159)
at e (angular.js:26673)
at b.$eval (angular.js:17958)
at b.$apply (angular.js:18058)
at HTMLFormElement.<anonymous> (angular.js:26678)
at bg (angular.js:3613)
at HTMLFormElement.d (angular.js:3601)
This is my service.js code :
.service('menuFactory', ['$resource', 'baseURL', function($resource,baseURL) {
this.getDishes = function(){
return $resource("localhost:3000/"+"dishes/:id",{update:{method:'PUT' }});
};
}])
and this is my controller code :
.controller('DishCommentController', ['$scope', 'menuFactory', function($scope,menuFactory) {
$scope.mycomment= {rating:"5", comment:"", author:""};
$scope.dish.comments.push($scope.mycomment);
menuFactory.getDishes().update({ id:$scope.dish.id }, $scope.dish);
}])
why angular doesn't recognize the update method , I had the same issues with get method , but after updating my angular to 1.6.0 version the problem with get method solved . but now I have the same problem with Update method.
What I am doing wrong here?
I think you might be calling $resource incorrectly.
Documentation and look at the usage:
$resource(url, [paramDefaults], [actions], options);
You were sending in actions as the paramDefault parameters, so just enter an empty literal for that parameter, unless you want to customise it.
Change
$resource("localhost:3000/"+"dishes/:id",{update:{method:'PUT' }});
to
$resource("localhost:3000/"+"dishes/:id",{}, update:{method:'PUT' }});
I'm trying to lazy-load components. The component is an html fragment with an embedded script tag that contains the controller.
<script>
... controller code .....
</script>
<div>
... template ....
</div>
The fragment is generated in ONE html request so I cannot use templateUrl AND componentURL in the state definition.
I have tried to use the templateProvider to get the component, than extract the script code for the function and register it using a reference to the controllerProvider.
I'm sure there must be a better way to do this than the ugly solution I have come up with. I make a global reference to the controllerpovider, then I read the component thru the templateProvide using a getComponent service. Next I extract the script and evaluate it, which also registers the controller.
See the plunker for the way I'm trying to solve this.
.factory('getComponent', function($http, $q) {
return function (params) {
var d = $q.defer();
// optional parameters
$http.get('myComponent.html').then(function (html) {
// the component contains a script tag and the rest of the template.
// the script tags contain the controller code.
// first i extract the two parts
var parser = new window.DOMParser();
var doc = parser.parseFromString(html.data, 'text/html');
var script = doc.querySelector('script');
// Here is my problem. I now need to instantiate and register the controller.
// It is now done using an eval which of cours is not the way to go
eval(script.textContent);
// return the htm which contains the template
var html = doc.querySelector('body').innerHTML;
d.resolve(html);
});
return d.promise;
};
})
Maybe it could be done using a templateProvider AND a controllerProvider but I'm not sure how to resolve both with one http request. Any help / ideas would be greatly appreciated.
Here's a working plunkr
You do not have access to $controllerProvider at runtime, so you cannot register a named controller.
UI-Router doesn't require named/registered controller functions. { controller: function() {} } is perfectly valid in a state definition
However, if you need the controller to be registered, you could use a tool like ocLazyLoad to register it.
UI-Router links the controller to the template, so there's no need for ng-controllersprinkled in the html.
Here's how I hacked this together. getController factory now keeps a cache of "promises for components". I retained your eval and template parsing to split the response into the two pieces. I resolved the promise with an object containing the ctrl/template.
component factory
.factory('getComponent', function($http, $q) {
var components = {};
return function (name, params) {
if (components[name])
return components[name];
return components[name] = $http.get(name + '.html').then(extractComponent);
function extractComponent(html) {
var parser = new window.DOMParser();
var doc = parser.parseFromString(html.data, 'text/html');
var script = doc.querySelector('script');
// returns a function from the <script> tag
var ctrl = eval(script.textContent);
// return the htm which contains the template
var tpl = doc.querySelector('body').innerHTML;
// resolve the promise with this "component"
return {ctrl: ctrl, tpl: tpl};
}
};
})
myComponent.html
<script>
var controller = function($scope) {
$scope.sayHi = function() {
alert(' Hi from My controller')
}
};
// This statement is assigned to a variable after the eval()
controller;
</script>
// No ng-controller
<div>
Lazyloaded template with controller in one pass.
<button ng-click="sayHi()">Click me to see that the controller actually works.</button>
</div>
In the state definition:
I created a resolve called 'component'. That resolve asks the getComponent factory to fetch the component called 'myComponent' (hint: 'myComponent' could be a route parameter)
When it's ready, the resolve is exposed to the UI-Router state subtree.
The state is activated
The view is initialized
The controller provider and template provider inject the resolved component, and return the controller/template to UI-Router.
Smell test
I should mention that fetching a controller and template in a single html file and manually parsing smells wrong to me.
Some variations you could pursue:
Improve the getComponent factory; Split the component into html/js and fetch each separately. Use $q.all to wait for both fetches.
Use ocLazyLoad to register the controller globally with $controllerProvider
Fetch and store the template in the $templateCache.
Error: registerService.getRegisterResponse is not a function
I getting Above Error on console of the web browser. While Accessing the a method(i.e saveRegisterResponse()) from Controller (i.e RegistrationCtrl) as registerService.getRegisterResponse() Method in registerService.
Here it is clear cut code.... For Both registerCtrl(controller) & regiterService(Service)...
Am placed both Service and Controller in app.js
**registerCtrl(Controller).**
var app=angular.module("app.chart.ctrls",['ngSanitize']);
app.controller("registrationCtrl",["$scope","$location","logger","registerService",function($scope,$location,registerService){
registerService.getRegisterResponse();
}]);
**registerService(Service)**
app.factory('registerService', function () {
var registerResponse = {};
return {
getRegisterResponse:function () {
return "xyz";
}
};
});
While Controller is loading am getting the Error
Angularjs Error: registerService.getRegisterResponse is not a function
How to Resolve it ? Thanks in Advance ...:)
It looks like you did not add logger as one of your controller's function arguments, which makes angular look for getRegisterResponse in your logger. Change your code to something like:
app.controller("registrationCtrl",
["$scope","$location","logger","registerService",function($scope,$location,logger, registerService){
registerService.getRegisterResponse();
}]);
Generally, I'd do the following and there would be an ng-app in my HTML:
var myApp = angular.module("myApp", []);
myApp.controller("AttributeCtrl", function ($scope) {
$scope.master = {
name: "some name"
};
});
However, I need to manually bootstrap angular because I'm only using it in a part of my app that is loaded via jQuery's $.load(). If I do the following:
main.js - this is where the page I want to use angular on is being pulled in
$("#form").load(contextPath + url, params, function() {
angular.bootstrap($("#angularApp"));
});
And then the page being pulled in has it's own javascript:
function AttributeCtrl($scope) {
$scope.master = { name: "some name"};
}
This works, however, ideally, I'd like my controllers to be scoped at the module level. So I modified the above code like so
main.js
$("#form").load(contextPath + url, params, function() {
angular.bootstrap($("#angularApp", ["myApp"]));
});
and then...
var app = angular.module("myApp"); // retrieve a module
app.controller("AttributeCtrl", function($scope) {
$scope.master = { name: "some name"};
});
Retrieving the module this way doesn't seem to work, though. Am I doing something wrong?
You cannot create a controller after you've bootstrapped the app. See the documentation for angular.bootstrap.
You should call angular.bootstrap() after you've loaded or defined your modules. You cannot add controllers, services, directives, etc after an application bootstraps.
I don't know if this is just in the example code you have here but:
angular.bootstrap($("#angularApp", ["myApp"]));
should be
angular.bootstrap($("#angularApp"), ["myApp"]);
Your code for retrieving the module should work.
Updated
They updated the documentation and now it reads like this
Each item in the array should be the name of a predefined module or a
(DI annotated) function that will be invoked by the injector as a run
block. See: {#link angular.module modules}
It seems a bug.
The way you implemented to retrieve the module is correct. Just quote it from the doc to make it clear since it may not be well-known.
When passed two or more arguments, a new module is created. If passed
only one argument, an existing module (the name passed as the first
argument to module) is retrieved.
For the problem you mentioned, long story short...
The bootstrap function calls createInjector with the module list ['ng', ['ngLocale', function(){...}] , 'myApp'] (the last one is the module you passed in)
function bootstrap(element, modules) {
...
var injector = createInjector(modules);
Inside createInjector(), it calls loadModules for each module passed in
function createInjector(modulesToLoad) {
forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });
And loadModules calls angularModule, which is initialized as angularModule = setupModuleLoader(window);, which creates the object window.angular.module
function loadModules(modulesToLoad){
....
var moduleFn = angularModule(module); // triggers the error
The the error occurs, since angularModule takes 2nd parameter as requires. Without it, it will throws an exception on this line (line 1148) throw Error('No module: ' + name);
Reported: https://github.com/angular/angular.js/issues/3692
Not sure if this counts as a bug or an implementation decision (albeit a seemingly poor one). Adding an empty array solves the undefined require problem that you were having and should solve your problem overall.
var app = angular.module("myApp", []); // create a module
app.controller("AttributeCtrl", function($scope) {
$scope.master = { name: "some name"};
});`
Also, in your fiddle you call {{name}} which won't render. You should be calling {{master.name}}
Edit
Thank you all for the downvotes .. Here's a working example. Good luck!
http://plnkr.co/edit/UowJpWYc1UDryLLlC3Be?p=preview