I have a function in my BlogController which changes the height of a div.
$scope.setTopBackgroundHeight = function (screenProportion, targetDiv) {
globalService.setTopBackgroundHeight(screenProportion, targetDiv);
};
I am using this controller on a few pages, but only want to call this function on one page. So I put the call in my view as follows.
<div id="primary"
class="content-area blog-page"
ng-controller="blogCtrl">
{{$scope.setTopBackgroundHeight("half", ".background-container");}}
</div>
Now, this works. But is calling a function from within curly braces in the view ok to do style wise? I've tried to find examples of doing something like this in the angular way, but can't see anything. Should it be in some ng directive?
Yes, all DOM manipulation should be done inside directives. So In this case it'd be better if you had a directive attached to the div that called that service method.
HTML:
<div id="primary"
class="content-area blog-page"
ng-controller="blogCtrl"
setBGHeight>
</div>
JS:
app.directive('setBGHeight', function(globalService) {
return {
link: function() {
globalService.setTopBackgroundHeight("half", ".background-container");
}
}
));
This is what directives are for. Make sure to prefix them like angular does with "ng-click" but don't use ng.
Related
I want to update argument of ng-click of button but not able to do it please help me... my code is
in controller
$scope.trCategoryId = 0;
and setting up this value in other function like
$scope.setClick = function (CategoryId) {
$scope.trCategoryId = CategoryId;}
in html i have define bellow
<button ng-click="ActiveTag('step1',{{trCategoryId}},0)" id="btnrename">Create</button>
it is not calling up ActiveTag function
Glad my comment worked out for you, adding it below as a solution:
Angular related attributes prefaced with ng- auto evaulate so
{{trCategoryId}} within any ng- is a no-no. It evaluates variable names against scope inside automatically, no need for the {{}}.
<button ng-click="ActiveTag('step1',trCategoryId,0)" id="btnrename">Create</button>
I have the following structures
<div ng-controller='ctrlA'>
<button ng-click='updateFactoryData(data)'></button>
<custom-dir>Custom directive with ctrlB</custom-dir>
<custom-dir>Custom directive with ctrlB</custom-dir>
<custom-dir>Custom directive with ctrlB</custom-dir>
...
<other-custom-dir>Custom directive with ctrlC</other-custom-dir>
<other-custom-dir>Custom directive with ctrlC</other-custom-dir>
<other-custom-dir>Custom directive with ctrlC</other-custom-dir>
...
</div>
I have a dataFactory, which when user clicks the button, the updated data will store in dataFactory, the dataFactory is injected to both ctrlB and ctrlC.
The problem is, when data is updated after clicking the button, the changes do not reflect on both custom-dir and other-custom-dir, is there any way ctrlB and ctrlC's scope value automatically reflect the changes made in scope under ctrlA?
Thanks very much for the help!
Thanks all for the kind help!! I finally figure out why the change cannot be reflected, I watch the object parameter to see if there are changes, but watch only monitor the object reference instead of the actual content, after deep watching the object parameter, I can finally get the watch work! Thanks for all the help
<custom-dir para="{data: data}"></custom-dir>
Then in directive's link function
scope.$watch('para.data', function(n,o){
alert('changed')
}, true); //>> The true is important!!
The fact that you need to share scope is a bit weird knowing that you have a parent controller that can contain your $scope item
Pass the value to attribute in the <custom-dir> and <other-custom-dir>
<custom-dir data="data"> </custom-dir>
Observe the change from the directive
attrs.$observe('data', function(value){
// call your directive controller here ...
})
The Benefit :
By passing data from attribute, the directive do not have to know about the controller/the source of the data, so, this reduce dependecy.
It's considered a best practice to use "controllerAs" and no longer use $scope.
By writing:
<div ng-controller='ctrlA as a'>
<button ng-click='a.updateFactoryData(data)'></button>
<!-- ... -->
</div>
and:
function ctrlA () {
this.data = [];
this.updateFactoryData = function (data) {
//...
}
}
You access your controller's data with a.data everywhere inside your div.
Basically what you require is here is share the factory data changes in your directives. So you can bind your desired factory data using different approaches based on your requirements(i.e. # attribute,= 2 way model, & expression bindings) in directives and than watch those variables in directives link functions (i.e. ideal place where you needs to handle those watch conditions) for changes so once anything will update on factory (through button click), it will automatically propagated in your directives. Here is the example to do different bindings.
var myModule = angular.module('myModule', [])
.directive('myComponent', function () {
return {
restrict:'E',
scope:{
/* NOTE: Normally I would set my attributes and bindings
to be the same name but I wanted to delineate between
parent and isolated scope. */
isolatedAttributeFoo:'#attributeFoo',
isolatedBindingFoo:'=bindingFoo',
isolatedExpressionFoo:'&'
}
};
})
<my-component attribute-foo="{{foo}}" binding-foo="foo"
isolated-expression-foo="updateFoo(newFoo)" >
<h2>Attribute</h2>
<div>
<strong>set:</strong> <input ng-model="isolatedAttributeFoo">
<i>// This does not update the parent scope.</i>
</div>
<h2>Binding</h2>
<div>
<strong>get:</strong> {{isolatedBindingFoo}}
</div>
<h2>Expression</h2>
<div>
<input ng-model="isolatedFoo">
<button class="btn" ng-click="isolatedExpressionFoo({newFoo:isolatedFoo})">
Submit</button>
<i>// And this calls a function on the parent scope.</i>
</div>
</my-component>
I have made sample demo to illustrate the approach please check this.
I've looked all over SO and Google and seen a whole bunch of reasons why ng-show wouldn't work inside of ng-repeat (scope issues, binding issues, etc.) but I can't quite pin down why mine isn't working. I was hoping that an extra pair of eyes could help me out. I'm very new to Angular, so hopefully my code makes some sense.
The goal: when $scope.current_set changes, the visible lmf-optionset changes. Currently, only the first optionset loads via Decision_Tree:loaded, and then when I try to load the next one via clickbox:clicked, $scope.current_set changes, but the view won't update.
JS
angular.module('lmf.option_set', [])
.controller('OptionsetCtrl', ['$scope', 'Optionsets', 'Decision_Tree',
function($scope, Optionsets, Decision_Tree) {
$scope.Optionsets = Optionsets;
$scope.current_set = {
name: null
};
$scope.$on('clickbox:clicked', function() {
$scope.current_set = Decision_Tree.get_next_optionset();
});
$scope.$on('Decision_Tree:loaded', function() {
$scope.current_set = Decision_Tree.get_next_optionset();
});
}
])
HTML
<div ng-controller='OptionsetCtrl'>
<div ng-repeat='set in Optionsets.option_sets'>
<div ng-show="set.name == current_set.name" lmf-optionset="{{set.name}}"></div>
</div>
</div>
Apparently lmf-optionset creates an isolated scope for each entry. These child scopes have link to parent's current_set, but they doesn't maintain a two-way binding. So when you are replacing the current_set value in you event handlers, child scopes are unaware that current_set was changed, and they are still referring to the old value.
You can either rewrite your event handlers like this:
$scope.current_set.name = Decision_Tree.get_next_optionset().name;
Or you can use controller as construction like this:
<div ng-controller='OptionsetCtrl as vm'>
<div ng-repeat='set in Optionsets.option_sets'>
<div ng-show="set.name == vm.current_set.name" lmf-optionset="{{set.name}}"></div>
</div>
</div>
I am trying to render a text as html using ng-bind as the docs show
<div ng-bind-html="text"></div>
The problem is that Angular removes the style attribute and renders this:
"<mark style='background-color:#FF9DFF;'>APPLE</mark>."
to this:
<mark>APPLE</mark>
How to render as html and keep the styles?
I am using Angular version 1.2.6
You may try this function when you're doing ng-bind-html in your controller
$sce.trustAsHtml('myHTML'); //$sce would be the parameter with $scope in module
Hope this will work
$NgSanitizeDocs
First of all include angular-sanitize.js
<div ng-bind-html="deliberatelyTrustDangerousSnippet()"></div>
Then in the controller, add this method
pk.controller("createBlog", function($scope, $sce){
//ace needs to be injected in the controller.
$scope.deliberatelyTrustDangerousSnippet = function() {
return $sce.trustAsHtml($scope.htmlcontent); //html content is th binded content.
};
})
I am very new to angular js. I want to create an input box on click of particular div. Here I need to create element on div which repeating.
<div><div ng-repeat ng-click="create();"></div><div>
What will be the best way to do so?
DOM manipulation in Angular is done via directives (There is paragraph on 'Creating a Directive that Manipulates the DOM' here)
First, read through this excellent article: How do i think in Angular if i have a jQuery background
The Angular Team also provides a pretty neat tutorial, which definetly is worth a look: http://docs.angularjs.org/tutorial
While Angular is pretty easy and fun to use once you have wrapped your head around the concepts, it can be quite overwhelming to dive into the cold. Start slow and do not try to use each and every feature from the beginning. Read a lot.
I strongly recommend egghead.io as a learning resource. The video-tutorials there are bite-sized and easy to watch and understand. A great place for both beginners and intermediates. Start from the bottom here.
Some folks have done great things with Angular. Take a look at http://builtwith.angularjs.org/ and check out some source code.
Use an array and ng-repeat to do that. Have a look at the following code.
I crated scope variable as an empty array. Then created a function to add values to that array.
app.controller('MainCtrl', function($scope) {
$scope.inputFields = [];
$scope.count = 0;
$scope.addField = function(){
$scope.inputFields.push({name:"inputText"+$scope.count++});
}
});
I used ng-repeat with this array. and called the function on the click event of a div.
<div ng-click="addField()">Click here to add</div>
<div ng-repeat="inputField in inputFields">
<input type="text" name="inputField.name">
</div>
Check this working link
Update - Show only one text box on click
I created addField() as follows.
$scope.addField = function(){
$scope.newTextField = "<input type='text' name='myTxt'>";
}
To render this html in my view file I created a new directive called compile as follows.
app.directive('compile', function($compile) {
// directive factory creates a link function
return function(scope, element, attrs) {
scope.$watch(
function(scope) {
// watch the 'compile' expression for changes
return scope.$eval(attrs.compile);
},
function(value) {
// when the 'compile' expression changes
// assign it into the current DOM
element.html(value);
// compile the new DOM and link it to the current
// scope.
// NOTE: we only compile .childNodes so that
// we don't get into infinite loop compiling ourselves
$compile(element.contents())(scope);
}
);
};
});
Then used this directive in my view.html file
<body ng-controller="MainCtrl">
<div ng-click="addField()">Click to Add</div>
<div compile="newTextField"></div>
</body>
click here to view the working link