Angular $compile cant find directive - javascript

I have a current project based around single-page-applications (SPA) and wanted to implent a function that dynamically loads directives into my html based on which kind of SPA is required.
The relevant code for that is:
the part of my controller that should load the directive
function checkSpaType(x) {
if (x === "quiz") {
const directivePosition = document.getElementById("spa");
directivePosition.append($compile("<quizSPA></quizSPA>")($scope));
};
};
the directive itself
function quizDirective () {
return {
templateUrl: "templates/quizSPA.html",
controller: 'quizCtrl',
link: function quizSPA() {}
}
}
and of course it doesnt work as planned.
After I run the scripts the only thing that gets loaded in my HTML is the message
"[object HTMLUnknownElement]]"
iam very sure that angular just cant find my directive, but how do I make it visible to it?
Also the template folder is in the same folder as my index.html from where the site starts. So that shouldnt be a problem. Likewise I already tried renaming the tags I load the in the html, sadly to no effect.
Anyone has an idea?

I fixed it myself right now.
Had to change:
directivePosition.append($compile("<quiz-s-p-a></quiz-s-p-a>")($scope))
to:
const spaDirective = $compile("<quiz>")($scope);
directivePosition.append(spaDirective[0]);

Related

AngularJS: Dynamic injection of modules after loading another js file

My broader problem statement is to reduce the JS file size used in the main web page. I minified using grunt uglify to reduce it from 455KB to 140KB.
As a second step, I am removing unnecessary file(s) which are not required on main page. Hence I was able to reduce the initial JS file size to 90KB, with the remaining 50KB file to be loaded later on.
I used Ben Thielker's loadScript function mentioned in
Single page application - load js file dynamically based on partial view to dynamically load the JS file onto head.
Now the issue is that the modules defined in the 2nd JS file are not loaded as
their dependency could not be mentioned earlier at the start of app(Would throw error). I want to load the modules present in 2nd JS file dynamically.
I tried the below in callback function of loadScript mentioned earlier:
angular.module('reportsApp', ['reportsApp.DList', 'reportsApp.item', 'reportsApp.Filters', 'reportsApp.Download'])
.controller('ReportsCtrl', ['$scope', '$rootScope', '$injector', function($scope, $rootScope, $injector) {
$rootScope.accessDenied = !$scope.accessReports;
$rootScope.loadScript('public/js/grid.min.js','text/javascript','utf-8', function() {
console.log('****************grid.min.js loaded successfully.....');
var grid;
var bool = $injector.has('reportsApp.Grids');
console.log(bool);//outputs "false"
if(bool) {
grid = $injector.get('reportsApp.Grids');
}
});
}])
But the above code does not even detect the module.
When I looked into angular's createInjector function, I found they are adding a string 'Provider' at the end of the modulename. Not sure if this is messing things up.
Also, this is the reportsApp.Grids module's 1st line:
angular.module('reportsApp.Grids', ['ui.grid'])
Here, reportsApp.Grids is present in the initial JS file itself,
but 'ui.grid' is only present in the 2nd JS file loaded later on.
How exactly should I use $injector.invoke function here?
OR
What is the best approach for this?

Angular Js how to show dynamic content

I am completely new to ANgularJs. As part of one project my page should show some content dynamically is changes in database. This changed vale can be obtained by a http get.
Before I try the complete scenario, I just wanted to see if is working atleast locally by taking a local variable. But its not working please suggest me how do I handle this.
angular.module('MyApp') .controller('HomeCtrl', function HomeCtrl($scope, $alert, $auth,$location) {
Counter=10;
Counter=Counter+1;
$scope.user={};
$scope.user.counter=Counter;
}
HomeCtrl($scope,$alert,$auth,$location);
);
It looks like you need to remove the following line:
HomeCtrl($scope,$alert,$auth,$location);
As you are still in the controller function call
remove
HomeCtrl($scope,$alert,$auth,$location);
but there were some other things also wrong..
working version:
fiddle -- http://jsfiddle.net/beLbv6L1/

Angular translate

in my app I would like to add functionality to translate page into all languages that user has set in browser and if none of them is available translate into default english... Problem is browser inconsistency with language support. I found a workaround for this, I make a http call to some webservice which returns user languages. It is done in app.run
app.run(function($rootScope, UserDataService, $translate){
UserDataService.getUserBrowserLanguage().then(function(language){
var langArr = language.split(',').map(function(el){
return el.split(';')[0].split(/-|_/)[0];
});
$translate.fallbackLanguage(langArr)
$translate.preferredLanguage(langArr[0]);
$translate.use(langArr[0]);
});
});
and in app config:
app.config(function ($routeProvider, $translateProvider) {
$translateProvider.useStaticFilesLoader({
prefix: '/languages/',
suffix: '.json'
});
});
section because I can't make http call in config and it fails... :/ langauges are loaded but the translation isn't changed... What am I doing wrong? Here is plunker:
http://plnkr.co/edit/41SngK2tCTeaq8IhMbcM
it doesn't display anything no translations... why? :( I would be very pleased with any help.
As for your question the view doesn't show anything due to the following errors:
Few mistakes:
First of all, ng-app should be moved to the html tag.
<html ng-app="translateApp">
Second, if you use a variable from a controller you should use ng-controller.
<div ng-controller="mainCtrl">
Last, when you bind a variable from the view to the controller the variable should be on the $scope.
$scope.translation = $translate.instant('GENERAL');
Fixed your plunker with my comments: Plunker.
As for the way $translate works, I am not really familiar with this service but I will try and have a look.
EDIT:
I studied $translate service in order to give you a full answer including fixing the way you used Translate, So first of all I put a timeout of 2 seconds before trying to use translate.instant, the reason is that I am letting translate loading the JSON files in the config.
I have added 2 buttons so you could switch between the languages and see it is working.
Enjoy! Here is the updated working Plunker.
Here is translate documentation site I used.

Running jQuery code in MEAN.JS stack

I'm starting to work with NodeJS, and more expecifically with MEAN.JS. I'm trying to run some custom JS code, using JQuery, but no matter where i put the code, it nevers runs as expected. This is my script:
$(document).ready(function(){
var tooltips = $('[data-toggle="tooltip"]');
tooltips.tooltip();
});
I tried putting it in the body of the page, in a separate script, but nothing. When I debug in Chrome, the variable tooltips does not contain any elements, but if I execute the same code in Chrome's console, then it works. It seems to me that despite the $(document).ready() thing, the DOM is not ready when the code executes. Maybe AngularJS is doing its magic at the same time and that interferes.
Is there somethign i need to do so that the code will get executed? Do I have to load it after/before something?
Thanks for any help.
I would suggest creating a directive instead of applying it in a dom ready:
angular.module("myModule")
.directive('tooltip', function () {
return {
restrict: 'A',
link: function (scope, elem) {
$(elem).tooltip();
}
}
});
Now, any time you use the tooltip or data-tooltip attribute on an element in one of your templates, the tooltip plugin will be applied to it.
Disclaimer: i have not tested this code, and in the end would suggest not using jquery for this. Instead, use angular-bootstrap-tooltip or a similar angular solution
Tooltips will not contains any elements as it is limited to the scope of the anonymous function you specified for $(document).ready(). Second, "tooltips" is misspelled in the variable declaration. Try this code to help you debug:
$(document).ready(function(){
window.$tooltips = $('[data-toggle="tooltip"]');
$tooltips.tooltip();
});
Now you can go into the console and evaluate the variable $tooltips to see if it is there. Note: I prefixed the variable with a $ to help identify it as a jQuery object. Don't confuse it with the built-in Angular services.
Also, Angular will not execute JavaScript within templates it generates pages from. Be sure to specify external JavaScript in the main page output or place this code to be executed when Angular loads the view.

Stuck with Angular-UI TinyMce

I'm trying to use the Angular-UI TinyMCE directive in my Angular app.
What happens is, I query an endpoint, it returns an array of objects. I have a function that then converts that to a long string with HTML tags in it. Then that data is set to a $scope.tinymceModel
This all works fine. I can console.log($scope.tinymceModel) and its the proper data.
The problem is the HTML parse function needs to run after the endpoint query is returned. So I've called the function inside the .success() callback. For some reason when I set the $scope.tinymceModel inside of the callback the TinyMCE directive ignores it. Even if I make it $scope.tinymceModel = 'test' but if I place $scope.tinymceModel = 'test' outside of the callback it shows up in tinymce just fine.
This tells me that for some reason when the TinyMCE directive is loaded it needs the tinymceModel to already be populated with data. I'm not sure how I get around this.
This also tells me that I may have another problem after this. The next task with TinyMCE is the user can then edit the text, click a button and the app will send a POST with the updated info inside tinymceModel If this was a regular text box it would be simple because of the data-binding. However it seems TinyMCE doesn't play well with databinding.
Any ideas?
I've attempted to recreate what you're describing (substituting $http with $timeout) to no avail. Here's my solution and it seems to be working just fine.
HTML:
<div ng-controller="MainCtrl">
<textarea ui-tinymce="" class="form-control" ng-model="someHtml"></textarea>
</div>
JavaScript:
angular.module('testTinymceApp')
.controller('MainCtrl', function ($scope, $timeout) {
$timeout(function() {
$scope.someHtml = '<h1>HELLO THERE</h1>'
}, 7000);
// This does the same thing with an XHR request instead of timeout
// $http.get('/some/data/').success(function(result) {
// $scope.someHtml = '<h1>HELLO THERE</h1>'
// });
});
I thought maybe you could compare with your own application? I know for a fact that this works with XHR requests. I'm building a CMS at work that uses what I assume is an identical workflow.
The someHtml attribute in this snippet will also be valid HTML under the covers, so sending it back in a POST request should be extremely easy.
If this is not sufficient, please provide further explanation.
Figured it out!, the issue has to do with a bug in the TinyMCE Directive. By default there is no priority set. Setting it to a value of 1 or higher fixes it. It seems that the current version of Ui-TinyMCE Directive has this fixed, but the version I pulled down less than a month ago didn't have it fixed.

Categories