I tried to create a Marionette module. When I access the template using jQuery in the module, it returns undefined. It happens for with or without default 6 arguments.
Note:
in the main.js this variable returns properly only in the module it returns undefined.
//App.module("LineModule", function(LineModule, App, Backbone, Marionette, $){
App.module("LineModule", function(LineModule){
console.log('LINE DRAFT : ' + $('#line-grid-content-template').html()); // undefined
});
What could be the reason? how can I fix it?
Thank you.
This will normally happen if #line-grid-content-template has not yet been added to the DOM. A few places to first check are, make sure it has the right ID (it's not a class or a miss spelling) and also that who ever is responsible for rendering the div has rendered it before you try to access it via the jQuery selector.
Related
I just spent an hour figuring out a type. I had a component:
<my-component on-info-updated="vm.onInfoUpdated(info)"/>
Unfortunately the function in my controller was:
onInfoUpdate(info) { ... }
Update, note Updated.
Angular just swallowed this error. No warning, no nothing. Is there any way of getting the browser or Angular to report this?
Angular 1 is pretty relaxed about custom attributes in the html as directive scope bindings are put together in the browser. Most browsers would render the attribute and its value as is, with no harm being caused.
With Angular 2+, the (TypeScript) compiler will normally throw an error if the template was wrongly set up like in your example.
I'm trying to build custom radio buttons, and I've discovered that my controllers are being executed twice for each instance. I have not specified the view controller twice. That seems to be the common problem. I'm using angular-routing, and the relevant snippet for that is this:
$routeProvider.when('/:action', {
templateUrl: function (params) {
if (!params.action) params.action = 'Index';
return '_' + params['action'];
}
});
I use ng-controller in the template. The routeChangeSuccessful event (or whatever it's called) fires, and it compiles everything normally, but it seems to follow up with some post link function that also compiles everything; thus the double instances.
What am I doing wrong? How can I avoid the duplicate calls?
Update
I've discovered that it's recompiling the initial view, whatever that was, when routing through AngularJS. I can work around this by adding a secret blank page that is always hit first (I'm developing in an .NET MVC project, so I can control that through the MVC routing), but that seems rather silly.
Why is ngRoute recompiling the initial view every time? Is there an elegant workaround?
Last I checked, ngView doesn't prevent the compilation of the template that is initially fetched, and in fact it recompiles it when the view changes before replacing it and compiling the template fetched by ngRoute.
To resolve this, have only AngularJS requests return templates. Return a blank template otherwise. I handle this by having the AngularJS requests include an underscore prefix. In the MVC routing, if the underscore is there, return the requested partial; otherwise, return the layout with an empty body.
I have a bit of a problem with an Angular application. Basically I want to manipulate the scope outside of the application itself. If I type in the console:
$scope = angular.element($('.lead-system')).scope()
I can use $scope with $apply and it all works fine. However, when I use this in a rails coffeescript file:
angular.element(document).ready ->
console.log angular.element($('.lead-system')).scope()
It logs undefined and of course I can't use $apply with that.
What's up with that? I'm loading the JS files in this order:
app.js <-- Main angular app initializer
pending.js.coffee <-- The file listed above
lead_controller.js <-- The controller of the scope I'm trying to access
Wrap it in the $timeout, just to check if it will work then. That should tell you if this can be fixed by different timing or give you ideas for further exploration.
My recommendation though would be to fire an event (emit/broadcast or even arbitrary external thing in your case) in controller and in reponse to that event manipulate the scope. You could even pass the scope as parameter for convenience.
I would like to have few global variables that are UI related (i.e. open menu state). I decided to put these in $rootScope so they're always accessible.
This is the code I've written:
(function (angular) {
angular
.module("App", [])
.run(["$rootScope", function ($rootScope) {
angular.extend($rootScope, {
ui: {
menu: false,
...
}
});
}]);
})(angular);
I've deliberately used angular.extend, to make sure that consecutive manipulations to the same object are retained. And I think it's also more clean and safe than adding several properties to any object one by one.
Problem
Upper code doesn't do anything though. When I run my application and check root scope by calling:
$("body").scope().$root.ui
I get undefined until some property within ui gets manipulated by ng-click directives on my application. Only then my ui gets a reference... But it's still not the one I've defined in the run() function but rather angular generated object property that ng-click directive generated as per expression.
What am I doing wrong?
Resolved - module got overwritten
Ia managed to resolve it myself. Code contained in the upper question isn't sufficient to show the actual problem in my application. The problem was the way I was loading module requirements and file ordering.
I'm loading files in this order:
app.js
routing.js
service.something.js
...
filter.something.js
...
So I thought to add module requirements to my app module in subsequent files (make ti actually modularized). This would make it simple to either include or exclude particular files without any runtime errors. It would also allow loading additional files dynamically as application runs.
The problem with my code was that I've overridden my original module in subsequent files. When I added all module requirements into app.js everything everything started working.
Possible workaround
I can see that I'm not the only person that would like this kind of functionality. Lasy module requirements loading is possible as per this Google groups' post.
What it does is it creates a new injector function
instanceInjector.loadNewModules = function (mods) {
forEach(loadModules(mods), function(fn) { instanceInjector.invoke(fn || noop); });
};
that can later be used by individual modules to add themselves as requirement to the main application module by doing this:
$injector.loadNewModules(["Module1", "Module2", ...]);
Although it would be much better (my opinion) if there was an additional function on Module type called requires() so one could do this instead:
angular.module("MainModule").requires(["AdditionalModule", "OtherModule", ...]);
I think that would make it more concise and easy to use and understand.
I am seeing some strange behavior that I'm hoping someone can explain.
From the render method in a backbone view I have been attempting to do the following:
this.$(".msg").colorbox();
And
this.$el.find(".msg").colorbox();
However in both cases, although the msg elements are located, when trying to invoke the colorbox method on the returned elements I get an exception that the method is not defined.
However when I use:
$(this.el).find(".msg").colorbox();
All is well. Is anyone aware of why this might be?
It is a common issue. Surely colorbox is a jQuery plugin. The jQuery plugin is injected until the View's Element is added to the DOM of your Page.
I mean, your code is normal to fail with the natural behavior.
$('body').append( view.render().el );
But if you do this, it will works:
$('body').append( view.el );
view.render();
Third party Backbone.js Plugins has a method "named" onRender that is executed after render the View(and assuming that added to the DOM). But if you do not work with additional Backbone.js Plugins just be sure to call the colorbox until your View was added to the DOM.
Shooting in the dark...
this.$el and $(this.el) are differente instances even if both make reference to the same DOM element.
Maybe since the moment Backbone did precompile this.$el = $(this.el) to the moment you call this.$el.colorbox() something has happend so this function is not available and it has never been available in the instance this.$el.
I don't know what is colorbox() but if this is part of a third part jQuery plugin can be important the order in that your JS code is loaded?