I want to create a div on click of a button:
the div should be like this:
<div class="my-blur"><div>
I am doing this:
$scope.showFloatingActioButtons = function() {
var newEle = angular.element('<div class="my-blur"></div>');
$compile(newEle)($scope);
}
You are almost there... you just need to add that element to the DOM somehwere.
angular.element('someselector-or-dom-element').append(newEle);
And unless you have bindings or directives on your new element, there is no reason to compile it.
I've added a running example to help clear up any confusion.
var app = angular.module('my-app', []);
function MyCtrl(){}
MyCtrl.prototype = {
addElement:function(){
var newEle = angular.element("<div class='red'></div>");
var target = document.getElementById('target');
angular.element(target).append(newEle);
}
};
app.controller('myCtrl', MyCtrl);
.red{
margin: 10px;
height:20px;
background-color:red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
<div ng-app="my-app" ng-controller="myCtrl as $ctrl">
<button type="button" ng-click="$ctrl.addElement()">Add Element</button>
<div id="target"></div>
</div>
Related
I wanted to disable a div section using ng-disabled, but it dint work. I've also tried using fieldset in place of div.
ng-disabled seems not working.
Below is the view part:
<div ng-disabled="model.disableDate">
<div>Date</div>
<div ion-datetime-picker ng-model="model.timeEntryDate" ng-change="onTimeEntryDateChange()" date="true" time="false" monday-first="true" am-pm="true">{{model.timeEntryDate|| "Select" | date: "dd/MM/yyyy"}} <i class="icon ion-ios-calendar-outline"></i> </div>
</div>
This is the controller part:
if ($scope.model.pageState === condition) {
$scope.model.disableDate = true;
}
Any way this calender is being popped even on the disabling condition.
You can't disable DIV. Disable work with button and input types only. You can try with css. Use ng-class.
<div ng-class="{ 'div-disabled': model.disableDate}"> // give condition here as per your scenario
.div-disabled
{
pointer-events: none;
opacity: 0.5;
background: #CCC;
}
You can create an attribute directive to disable any div. See below:
var app = angular.module("myApp", []);
app.directive("disableSection", function() {
return {
restrict : "A",
link:function(scope,element,attr,ctrl){
element.css({
cursor :"not-allowed",
opacity: "0.5",
background: "#CCC"
});
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp">
<div disable-section>This is disabled div</div>
</body>
You can use pointer-events: none for disabling the div:-
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.obj = {};
$scope.obj.disabled = false;
$scope.clickMe = function(){
alert('div is enabled');
}
});
.disabled {
pointer-events: none;
}
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-class="(obj.disabled)?'disabled':''" style="width:100px;height:100px;border:1px solid black">
<a style="cursor:pointer" ng-click="clickMe()">Click Me</a>
</div>
<button ng-click="obj.disabled = !obj.disabled">{{(obj.disabled)?'Enable':'Disable'}}</button>
</div>
I am trying that on a button click, a div and and input tag are created and the input tag contain ng-model and the div has binding with that input.
Kindly suggest some solution.
You can create the div and input beforehand and and do not show it by using ng-if="myVar". On click make the ng-if="true".
<button ng-click="myVar = true">
In controller : $scope.myVar = false;
$scope.addInputBox = function(){
//#myForm id of your form or container boxenter code here
$('#myForm').append('<div><input type="text" name="myfieldname" value="myvalue" ng-model="model-name" /></div>');
}
Here is another solution, in which there's no need to create a div and an input explicitly. Loop through an array of elements with ng-repeat. The advantage is that you will have all the values of the inputs in that array.
angular.module('app', [])
.controller('AppController', AppController);
AppController.$inject = ['$scope'];
function AppController($scope) {
$scope.values = [];
$scope.add = function() {
$scope.values.push('');
};
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="AppController">
<button ng-click="add()">Click</button>
<div ng-repeat="value in values track by $index">
<input type="text" ng-model="values[$index]"/>
<div>{{values[$index]}}</div>
</div>
<pre>{{values}}</pre>
</div>
UPDATE. And if you want only one input, it's even simpler, using ng-show.
angular.module('app', []);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<button ng-click="show = true">Click</button>
<div ng-show="show">
<input type="text" ng-model="value"/>
<div>{{value}}</div>
</div>
</div>
You should use $compile service to link scope and your template together:
angular.module('myApp', [])
.controller('MyCtrl', ['$scope', '$compile', '$document' , function MyCtrl($scope, $compile, $document) {
var ctrl = this;
var inputTemplate = '<div><span ng-bind="$ctrl.testModel"></span>--<span>{{$ctrl.testModel}}</span><input type="text" name="testModel"/></div>';
ctrl.addControllDynamically = addControllDynamically;
var id = 0;
function addControllDynamically() {
var name = "testModel_" + id;
var cloned = angular.element(inputTemplate.replace(/testModel/g, name)).clone();
cloned.find('input').attr("ng-model", "$ctrl." + name); //add ng-model attribute
$document.find('[ng-app]').append($compile(cloned)($scope)); //compile and append
id++;
}
return ctrl;
}]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.angularjs.org/1.6.2/angular.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl as $ctrl">
<input type="button" value="Add control dynamically" ng-click="$ctrl.addControllDynamically()"/>
</div>
</div>
UPDATE: to add a new compiled template each time the button is clicked, we need to make a clone of the element.
UPDATE 2: The example above represents a dirty-way of manipulating the DOM from controller, which should be avoided. A better (angular-)way to solve the problem - is to create a directive with custom template and use it together with ng-repeat like this:
angular.module('myApp', [])
.controller('MyCtrl', ['$scope', function MyCtrl($scope) {
var ctrl = this;
ctrl.controls = [];
ctrl.addControllDynamically = addControllDynamically;
ctrl.removeControl = removeControl;
function addControllDynamically() {
//adding control to controls array
ctrl.controls.push({ type: 'text' });
}
function removeControl(i) {
//removing controls from array
ctrl.controls.splice(i, 1);
}
return ctrl;
}])
.directive('controlTemplate', [function () {
var controlTemplate = {
restrict: 'E',
scope: {
type: '<',
ngModel: '='
},
template: "<div>" +
"<div><span ng-bind='ngModel'></span><input type='type' ng-model='ngModel'/></div>" +
"</div>"
}
return controlTemplate;
}]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.angularjs.org/1.6.2/angular.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl as $ctrl">
<input type="button" value="Add control dynamically" ng-click="$ctrl.addControllDynamically()"/>
<div ng-repeat="control in $ctrl.controls">
<control-template type="control.type" ng-model="control.value"></control-template>
</div>
</div>
</div>
I study AngularJS, now try to add an attribute based on one (or multiple) condition(s).
But this code (CodePen here) doesn't seem to work:
function myController($scope) {
console.log("start");
$scope.item = { myBool: false };
$scope.myClick = function(e) {
var myHref = angular.element(e.delegateTarget).data(href);
console.log(myHref);
};
}
.test{background: lightblue; height: 50px; }
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div np-app ng-controller="myController">
<div class="test"
data-href="{undefined: !item.myBool, 'http://yes.com': item.myBool}"
ng-click="myClick($event);console.log('end');">click & see the console</div>
</div>
actually the data-href attribute should not be defined, as myBool == false...
Use interpolation for that:
angular.module('myApp', [])
.controller('myController', function($scope) {
console.log("start");
$scope.item = {
myBool: false
};
$scope.myClick = function(e) {
$scope.item.myBool = !$scope.item.myBool;
console.log(angular.element(e.target).attr("href"));
};
});
.test{background: lightblue; height: 50px; }
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController">
<div class="test" href="{{item.myBool ? 'http://yes.com' : undefined}}" ng-click="myClick($event)">
click & see the console
</div>
</div>
Finally, updated a little bit the Vanojx1 answer to:
angular.module('myApp', [])
.controller('myController', function($scope) {
console.log("start");
$scope.item = { myBool: false };
$scope.myClick = function(e) {
$scope.item.myBool = !$scope.item.myBool;
console.log(angular.element(e.target).attr("href"));
console.log(angular.element(e.target).attr("noarg"));
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController">
<div class="test" ng-attr-href="{{item.myBool? 'http://yes.com' : undefined}}" ng-click="myClick($event)">
click & see the console
</div>
</div>
Important improvements:
updated the Angular version to be > 1.3 (actually I used an ancient one);
used the ng-attr-xxx attribute that is removed (the attribute itself, not just its value) if its value estimated to undefined;
When I click the Not heart div, all Not heart div must hide and all Hearted div will show. When I click the Hearted div, all Hearted div must hide and all Not heart div will show. The same interaction to collection component. When the hearted div is showing, the heartNumber have to add 1. When the Not heart div is showing, the heartNumber have to delete 1.
My application architecture is like this:
heart folder is on:
https://jsfiddle.net/jiexishede/Ltsgnn86/1/
collection folder is on:
https://jsfiddle.net/jiexishede/hq6dju3c/1/
show folder is on:
https://jsfiddle.net/jiexishede/e9bxf1f9/1/
The code in index.html is below :
<body ng-app="app" ng-controller="controller">
<div style="margin-bottom: 10px">
<heart is-heart="heartBoolean"></heart>
<collection is-collection="collectionBoolean"></collection>
</div>
<div>
<shownumber collection-number="10" heart-number="10"></shownumber>
</div>
<div style="margin-top: 10px">
<heart is-heart="heartBoolean"></heart>
<collection is-collection="collectionBoolean"></collection>
</div>
</body>
<script src="angular.js"></script>
<script src="collection/collectionComponent.js"></script>
<script src="heart/heartComponent.js"></script>
<script src="show/showComponent.js"></script>
<script>
var app = angular.module('app',[]);
app.controller('controller', function ($scope) {
$scope.heartBoolean = true;
$scope.collectionBoolean = true;
})
</script>
<script>
collectionComponentFactoryFun('app','./collection');
showComponentFactoryFun('app','./show');
heartComponentFactoryFun('app','./heart');
</script>
Now, I have changed the text in the demo. The demo uses the variable named collectionBoolean and the variable named heartBoolean. If you change the boolean state in the component. I will vote your code, due to your code is not coupled.
I hope that is not too late.... According to what I see in your code I reckon that the main issue is with the way that you are setting up your main module and components.
I've just worked around a little bit I came up with this hope it will work.
angular.module('plunker', []);
angular
.module( 'plunker' )
.controller( 'MainCtrl', function ( $scope ) {
$scope.isHeart = true;
$scope.isCollection = true;
});
var HeartCtrl = function () {
var ctrl = this;
ctrl.$onInit = function () {
var isHeart = angular.copy( ctrl.isHeart );
console.log( 'isHeart : ', isHeart );
};
ctrl.$onChanges = function ( changes ) {
if ( changes.isHeart && !changes.isHeart.isFirstChange() ) {
ctrl.isHeart = angular.copy( changes.isHeart );
}
};
ctrl.clickHeartFun = function (boolean_number) {
ctrl.isHeart = boolean_number;
};
};
angular
.module( 'plunker' )
.component( 'heart', {
bindings: {
isHeart : '<'
},
templateUrl : 'heart.tpl.html',
controller : HeartCtrl
});
http://plnkr.co/edit/RJwYJ2iAxEQOV5jBwyXj?p=preview
I want to manipulate items in an array stored in a parent controller. When I manipulate the items, I want to do this from within an ng-repeat loop inside a child controller.
As far as I can tell, the array in the parent controller is being updated - in fact s===cs. I have read that $scope.$apply() might be the answer but I'm not sure how to call that using the "controller as" syntax below - or if that is even wise.
<html ng-app='app'>
<body ng-controller='parent_controller as pc'>
{{ pc.parent_name }}
<br>
Enter parent_name <input ng-model='pc.parent_name'/>
<br>
<button ng-click='pc.change_parent_name()'>change parent_name</button>
<div ng-controller='child_controller as cc'>
<div ng-repeat='item in pc.myarray' style='border:1px solid #ccc; margin:20px;'>
Item = {{ item }}
<br>
<button ng-click='cc.change_item_name($index)'>change item name</button>
</div>
</div>
<script src="js/jquery.min.js"></script>
<script src="js/angular.min.js"></script>
<script type='text/javascript'>
var app = angular.module('app',[]);
function parent_controller(){
var self = this;
window.s = self; // For debugging
self.myarray = ['a','b','c'];
self.change_parent_name = function () {
self.parent_name = 'changed!!';
}
}
app.controller('parent_controller',[parent_controller]);
function child_controller() {
var self = this;
window.cs = self; // For debugging
parent_controller.apply(self, arguments);
self.change_item_name = function(index){
console.log(index);
self.myarray[index] = 'changed';
}
}
app.controller('child_controller',[child_controller]);
</script>
</body>
</html>
Since the array has primitive string type, pass in the parent array and index into the child controller function and it should work fine.
self.change_item_name = function(items, index){
console.log(index);
items[index] = 'changed';
}
And the html changes to:
<button ng-click='cc.change_item_name(pc.myarray,$index)'>change item name</button>
You would be better off putting the child controller on the ng-repeat, and then using that to update the parent controller. $scope.$apply is not necessary. If you want to update the parent controller from the controller code, you are better off using a service to communicate between the two.
Moving the data source from the parent controller to a service and injecting that service into both controllers allows them to access the same data. [AngularJS API reference]
This example does that and adds a third controller to highlight the extent to which the data is shared across controllers.
ctrl_3 below also shows how $scope can be accessed using controller as syntax. $scope is only used for the console.log part - it isn't used for this service approach.
<html ng-app='app'>
<body ng-controller='a_controller as ctrl_1'>
{{ ctrl_1.parent_name }}
<br>
Enter parent_name <input ng-model='ctrl_1.parent_name'/>
<br>
<button ng-click='ctrl_1.change_parent_name()'>change parent_name</button>
<div><strong>ctrl_2</strong></div>
<div ng-controller='a_controller as ctrl_2'>
<div ng-repeat='item in ctrl_2.myarray' style='border:1px solid #ccc; margin:20px;'>
Item = {{ item }}
<br>
<button ng-click='ctrl_2.change_item_name(ctrl_2.myarray, $index)'>change item name</button>
</div>
</div>
<!-- an extra repeat of the myarray, this time using ctrl_1 for the repeat of myarray but ctrl_3 as the controller, just to show it all ties back to the same data source -->
<hr>
<div><strong>ctrl_3</strong></div>
<div ng-controller='a_controller as ctrl_3'>
<div ng-repeat='item in ctrl_1.myarray' style='border:1px solid #ccc; margin:20px;'>
Item = {{ item }}
<br>
<button ng-click='ctrl_3.change_item_name(ctrl_3.myarray, $index)'>change item name</button>
</div>
</div>
<script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js'></script>
<script type='text/javascript'>
angular.module('app',[])
.factory('DataService', [function() {
data = [ {'a':1}, {'b':2}, {'c':3} ];
return {
myarray : data
}
}])
.controller('a_controller', ['DataService', '$scope', function(DataService, $scope) {
var self = this;
window.s = self; // For debugging
console.log($scope);
self.myarray = DataService.myarray;
self.change_parent_name = function () {
self.parent_name = 'changed!!';
}
self.change_item_name = function(array,index){
array[index] = {'changed': 999};
}
}]);
</script>
</body>
</html>