I have a single kendo-window in my page and i want to load content to it every time i click a command. The content i want to load is either from x-kendo-template or from .html with expression in angular {{Sample}}. After the content is loaded, i tried to $compile the content to make use of the angular binding but it is not working. This is what i tried so far
On my markup
<base href="http://demos.telerik.com/kendo-ui/grid/angular">
<script id="tplAddNew" type="text/x-kendo-template">
Action in Add New: {{ Action }}
</script>
<script id="tplView" type="text/x-kendo-template">
Action in View: {{ Action }}
</script>
<div id="example" ng-app="Test">
<div ng-controller="MyCtrl">
<div kendo-window="winTesting"
k-visible="false"
k-modal="true"
k-pinned="true"
k-width="'500px'"
k-min-height="'200px'">
</div>
<button
kendo-button
ng-click="AddEntry()">Add Entry</button>
<button
kendo-button
ng-click="ViewContent()">View Content</button>
</div>
</div>
and here is my controller
var app = angular.module("Test", ["kendo.directives"]);
app.controller("MyCtrl", [
"$scope", "$compile",
function($scope, $compile) {
$scope.AddEntry = function() {
$scope.Action = "Add New";
$scope.winTesting
.refresh({
//url: '../References/Test-entry.html'
template: kendo.template($('#tplAddNew').html())
})
.setOptions({
title: "Create New User"
});
//$scope.$apply(function() {
// $compile($scope.winTesting.element)($scope);
//});
$scope.winTesting.open().center();
}
$scope.ViewContent = function() {
$scope.winTesting
.refresh({
//url: '../References/View-entry.html'
template: kendo.template($('#tplView').html())
})
.setOptions({
title: "View User Detail"
});
//$scope.$apply(function() {
// $compile($scope.winTesting.element)($scope);
//});
$scope.winTesting.open().center();
}
}
]);
lets assume that the content of Test-entry.html is the same as tplAddNew Template
Now, when i will use the $compile function, it will show an error of $apply already in progress
Any help would be appreciated. TIA
i also prepared a JSFiddle
Kendo has not really refined this widget yet. So in light of that use the $timeout service:
$timeout(function() {
$compile($scope.winTesting.element)($scope);
}, true);
The last boolean parameter does (more or less) a $scope.$apply. See the Documentation
Edit:
There is also some cool stuff you could do with the $parse service as well. You might find it useful as explained in this blog
Related
I wish I can handle this, but in the bad way...namely I need to use $cookieStore to check either the function called or not.
Every time to use push array then I need to use $cookieStore. But it seems not practical.
Here was my DOM:
<div ng-controller="MyCtrl">
<div>
<div ng-include="'temp2.html'">
Hello, {{name}}!
</div>
</div>
</div>
<script type="text/ng-template" id="temp2.html">
<div ng-controller="MyCtrl">Another View</div>
</script>
And my angularjs controller:
var myApp = angular.module('myApp',[]);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function MyCtrl($scope) {
$scope.name = 'Superhero';
alert(1);
}
alert(1) function will be called 2 times every times the page was called.
How to avoid this problem without using watcher?
My fiddle for your convenience. Thanks!
The controller would called be twice for both the views, i would suggest you to move controller specific code to init function and use ng-init in one of your views.
var Controller = function($scope) {
$scope.init = function () {
};
};
Your View
<div ng-controller="Controller" ng-init="init()"/>
Yo don't need to specify the Controller name again in the include.... if its the same as the parent one(same as controller of main page).
just go with this
<div ng-controller="MyCtrl">
<div>
<div ng-include="'temp2.html'">
Hello, {{name}}!
</div>
</div>
</div>
<script type="text/ng-template" id="temp2.html">
<div>Another View {{name}}</div>
</script>
Js Fiddel
name will be accessible in the view you included.
Hope it will help you..
I'm using Angular Bootstrap UI and I have a working tooltip.
HTML:
<div ng-app="helloApp">
<div ng-controller="helloCtrl as hello">
<a tooltip-trigger="click" tooltip-placement="bottom" uib-tooltip-html="<h1 ng-click='hello.clickInsideToSeeTheWorld()'>Click again!</h1>">Click me to see the tooltip</a>
</div>
</div>
Javascript:
angular.module('helloApp', ['ui.bootstrap'])
.controller('helloCtrl', helloCtrl)
function helloCtrl() {
var vm = this;
vm.clickInsideToSeeTheWorld = function() {alert(123)}
}
When I open up the tooltip, ng-click doesn't work. No alert appears. I receive no errors in my console. This is because the HTML isn't compiled. How can I properly compile the tooltip html to get this to work?
Extending the previous answer: You can probably use
uib-tooltip-template
instead of
uib-tooltip-html
when you exploit the angular template cache.
I understand that you maybe do not want to create an external template.html, but you do not have to do so. Simply try:
var app = angular.module("test", ['ui.bootstrap']);
app.controller("testController", function($scope, $templateCache) {
$scope.clickInsideToSeeTheWorld = function() {
alert(123)
}
if (!$templateCache.get ('template.html')) {
$templateCache.put (
'template.html',
'<a ng-click="clickInsideToSeeTheWorld()">Click again!</a>'
);
}
});
and
<div ng-app="test" ng-controller="testController">
<p style="margin-top: 5em;" uib-tooltip-template="'template.html'" tooltip-popup-close-delay="3000" >
Click me to see the tooltip
</p>
Here's an external plunker as well:
https://plnkr.co/edit/Dsi69MQg4NfgOSI5ClFh?p=preview
I added uib-tooltip-template instead uib-tooltip-html and changed this to $scope.
index.html
<body>
<script>
var app = angular.module("test", ['ui.bootstrap']);
app.controller("testController", function($scope) {
$scope.clickInsideToSeeTheWorld = function() {
alert(123)}
});
</script>
<div ng-app="test" ng-controller="testController">
<p style="margin-top: 5em;" uib-tooltip-template="'template.html'" tooltip-popup-close-delay="3000" >
Click me to see the tooltip
</p>
</div>
</body>
template.html
<a ng-click="clickInsideToSeeTheWorld()">Click again!</a>
Here is working Plunker
Or Alternative solution is for you to compile code yourself and then assign it to tooltip html
var sc = scope.$new( true ); //scope for html
sc.hello = {} // assign your hallo object to new scope
var compiledHtml = $compile( '<h1 ng-click="hello.clickInsideToSeeTheWorld()">Click again!</h1>')( sc );
Then you can set tooltip html to compiledHtml.
I'm using AngularJS for binding JS variables to my HTML content, and it works fine.
JS
var app = angular.module("Tabs", [])
.controller("TabsController", ['$scope', function($scope){
$scope.events = my_JS_object;
})
HTML
<div>{{events.test}}</div>
It works as long as my_JS_object.test is a simple string, like "Hello World", but once I try to put HTML tag in there, such as Hello <b>World</b> It doesn't use the tags as HTML elements, but as simple text. Which makes sense, only I have no idea how to make the HTML tags work.
As stated by Angular documentation, you can use inbuilt ng-bind-html directive to evaluate model string and insert resulting HTML into element.
Example:
If you have model value like:
$scope.myHTML =
'I am an <code>HTML</code>string with ' +
'links! and other <em>stuff</em>';
Use ng-bind-html like:
<p ng-bind-html="myHTML"></p>
For detailed information go through: https://docs.angularjs.org/api/ng/directive/ngBindHtml
Note: Don't forget to inject ngSanitize service in your app.
You need to use the ngBindHtml directive that properly evaluates the expression and inserts the resulting HTML into the element in a secure way. To do this, you must include a reference to angular-sanitize.js in your HTML and then in your angular module, inject ngSanitize.
Like so
var app = angular.module("Tabs", ['ngSanitize'])
.controller("TabsController", ['$scope', function($scope){
$scope.events = my_JS_object;
})
<div ng-controller="TabsController">
<div ng-bind-html="events.test"></div>
</div>
Here is a full working example:
(function(angular) {
'use strict';
angular.module('bindHtmlExample', ['ngSanitize'])
.controller('ExampleController', ['$scope', function($scope) {
$scope.myHTML = 'Hello This is <b>BOLD<b/>';
}]);
})(window.angular);
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0-beta.1/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0-beta.1/angular-sanitize.js"></script>
</head>
<body ng-app="bindHtmlExample">
<div ng-controller="ExampleController">
<p ng-bind-html="myHTML"></p>
</div>
</body>
Refer to the official angular documentation for details:
https://docs.angularjs.org/api/ng/directive/ngBindHtml
If you want to insert HTML into page you shouldn't do it this way.
There is sanitize for this task.
For example in your controller:
$scope.trustedHtml = "<b>Hello World</b>"
And in your html:
<div ng-bind-html="trustedHtml "></div>
Always check html if using a user given text before inserting.
Also don't forget to add ngSanitize as dependency while creating controller
It's easier to use transclusion if you want to embed custom HTML into your DOM tree.
angular.module('myApp', [])
.controller('MainCtrl', function ($scope) {
$scope.overwrite = false;
$scope.origin = 'parent controller';
})
.directive('myDirective', function() {
return {
restrict: 'E',
templateUrl: 'my-directive.html',
scope: {},
transclude: true,
link: function (scope) {
scope.overwrite = !!scope.origin;
scope.origin = 'link function';
}
};
});
<script src="https://code.angularjs.org/1.3.2/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MainCtrl">
<my-directive>
<p>HTML template</p>
<p>Scope from {{origin}}</p>
<p>Overwritten? {{overwrite}}</p>
</my-directive>
</div>
<script type="text/ng-template" id="my-directive.html">
<ng-transclude></ng-transclude>
<hr />
<p>Directive template</p>
<p>Scope from {{origin}}</p>
<p>Overwritten? {{overwrite}}</p>
</script>
</div>
I have an interface with a "settings" button that opens a modal window. What I want to do is update scope values from the original controller. For example, in the MainController, i define a "default" theme that is used to control the theme in the body tag.
$scope.theme = 'default';
In the controller, I am updating the value of $scope.theme from an input in the view with something like ng-click"changeTheme(newValue)" .. which updates $scope.theme and furthermore, the body's class is reflected by this value.
<body ng-controller="MainController" ng-class="{midnight: theme == 'midnight'}">
Here is the modal code in that controller
$scope.open = function (settings) {
$scope.settings = settings;
$modal.open({
templateUrl: 'myModalContent.html',
backdrop: true,
windowClass: 'modal',
controller: function ($scope, $modalInstance, settings) {
$scope.settings = settings;
$scope.submit = function () {
$modalInstance.dismiss('cancel');
}
},
resolve: {
settings: function () {
return $scope.settings;
}
}
});
};
And in the view ... here's what I have so far.
<script type="text/ng-template" id="myModalContent.html">
<form ng-submit="submit()">
<div class="modal-body">
<label>Label</label>
<input type="text" ng-model="settings.label" />
<label>Value</label>
<input type="text" ng-model="settings.theme" />
</div>
<div class="modal-footer">
<input type="submit" class="btn primary-btn" value="Close" />
</div>
</form>
</script>
This example works when sending back anything that is created in this new $scope.settings object. But what I want is for the new settings object to update the $scope.theme from the main controller as well. What am I missing?
The problem was I didn't give UI bootstrap nearly enough attention with their basic example. All I wanted was to find a way for the selection in the modal to update various scope values on the page. I've figured out out by messing with this example:
http://plnkr.co/edit/jpJX4WvHw0SSYm3pAAzq?p=preview
My trouble was understanding how to handle multiple variables changing from the modal. This is a very simple fork that illustrates what I was trying to initially understand:
http://plnkr.co/edit/RYNcURKjGhWxUBpUlAkD?p=preview
I have a model that I want to be editable, but for some reason nothing change, the textbox doesn't show up and the model is not being updated when using ng-view.
I can see the function enableEditor() being called using console.log.
If I write it inline instead of ng-view in the index.html without the profile.html everything works perfectly.
here are the files:
app.js
var proGamersApp = angular.module('proGamersApp', ['ngResource']).
config(function ($routeProvider) {
$routeProvider.
when('/', { controller: 'ProfileController', templateUrl: '/app/partials/profile.html' }).
otherwise({ redirectTo: '/' });
});
var ProfileController = function ($scope) {
$scope.init = function () {
$scope.title = 'first title';
};
$scope.init();
$scope.enableEditor = function () {
console.log('enableEditor()')
$scope.editorEnabled = true;
$scope.editableTitle = 'second title';
$scope.title = 'second title';
};
...
};
index.html
<!doctype html>
<html ng-app="proGamersApp">
<head>
<title>Pro Gamers</title>
<!-- Scripts -->
<script src="/app/lib/angular.min.js"></script>
<script src="/app/lib/angular-resource.js"></script>
<script src="/app/app.js"></script>
</head>
<body>
<div ng-view></div>
</body>
</html>
profile.html
<div ng-hide="editorEnabled">
{{title}}
Edit title
</div>
<div ng-show="editorEnabled">
<input ng-model="title" ng-show="editorEnabled">
Save
or
cancel.
</div>
Does someone know what I am doing wrong?
thanks
The link is adding to your address, causing the router to refresh the page and wack all your $scope vars. Instead of using blank anchors, use a span styled like an anchor:
span:hover {
cursor:pointer;
}
This only gives the cursor the pointer finger, customize the colors as you wish. Per your comments as well, don't add the target=_self to the href, add it after:
Save //prevent address bar change
As I said before though, use spans instead.