How to hide some element on screen resize in angularjs - angularjs

I am new in angularjs. I searched a lot to hide some html element on body resize but did't work. here is my controller code.
var app = angular.module('studentPage',[]);
app.controller ('studentController',function($scope, $window) {
var appWindow = angular.element($window);
appWindow.bind('resize', function () {
if($window.innerWidth < 600){
alert("hello");
$scope.ohh = true;
}
});
});
and here where i use ng-show
<div id="sidebar-wrapper" ng-show="ohh">

If you want to achieve this using AngularJS, you need to relaunch the digest cycle using $scope.$apply().
appWindow.bind('resize', function () {
if($window.innerWidth < 600){
$scope.ohh = true;
$scope.$apply();
}
});
Anyway, I think a cleaner way to do that is using CSS media queries:
#media only screen and (max-width: 599px) {
#sidebar-wrapper {
display: none;
}
}

You have to manually trigger the digest cycle using $apply() function , since what you are doing is out of angular context.Try the below code.
var app = angular.module('studentPage',[]);
app.controller ('studentController',function($scope, $window) {
var appWindow = angular.element($window);
appWindow.bind('resize', function () {
if($window.innerWidth < 600){
alert("hello");
$scope.ohh = true;
$scope.$apply()
} });});

You have to apply the scope changes by calling $scope.$apply().:-
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope, $window) {
var appWindow = angular.element($window);
$scope.ctrl = {};
$scope.ctrl.ohh = false;
appWindow.bind('resize', function() {
console.log($window.innerWidth);
if ($window.innerWidth < 600) {
$scope.ctrl.ohh = true;
$scope.$apply()
}
});
});
<!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">
<h1>THis is main content</h1><br>
<div id="sidebar-wrapper" ng-show="ctrl.ohh">This is shown after window width is less than 600
</div>
</div>

Related

angular $watch is not work with d3.js

look, click the button, $scope.optionis change, but $watch is not work, can`t console.log the option value , why?
I am sorry , it is my mistake , but it still is a problem in I use width d3.js
I use d3.js append a rect into page, and I want to when I click the rect can chagne the option value, but $watch is not work, why?
angular.module('myapp',[]).controller('myCtrl', function($scope){
$scope.option = '123';
$scope.d3TreeDraw = {
source : {
name: 'myTree'
},
updata: function(){
var _self = this;
var tree = d3.layout.tree().nodeSize([90, 60]);
var nodes = tree.nodes(_self.source).reverse();
nodes.forEach(function(d) { d.y = d.depth * 90; });
var svg = d3.select("body").append("svg")
.attr("width", 200)
.attr("height", 200)
var node = svg.selectAll("g.node")
.data(nodes)
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.style('cursor','pointer')
.on('click', function(d){
console.log('click'); // can console.log
$scope.option = '456';
console.log($scope.option) //is change
})
nodeEnter.append("rect")
.attr('width',150)
.attr('height', 30)
.style('fill', '#000')
}
}
$scope.d3TreeDraw.updata();
$scope.$watch('option', function(){
console.log('change:' + $scope.option); // when option is change,can not console.log
})
})
1) First You have taken myTree.onClick() and your function has onclick
So, the onClick() spelling mismatched.
Change button to <button ng-click="myTree.onclick()">456</button>
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<button ng-click="myTree.onclick()">{{data}}</button>
<br>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.firstName = "John";
$scope.lastName = "Doe";
$scope.data = '100';
$scope.myTree = {
onclick: function() {
$scope.data = '456';
}
}
$scope.$watch('data', function(){
console.log($scope.data);
alert($scope.data);
})
});
</script>
</body>
</html>
Here is a working DEMO.
EDIT:
By checking your edit, I saw that your scope assignment is outside of angular.
So, you need to $apply() the $scope
Change,
$scope.option = '456';
to,
$scope.$apply(function() {
$scope.option = '456'
});
The above method, runs the digest cycle manually, and apply the changes for the scope.
Performance:
If you write $scope.$apply() it will run complete digest cycle, which will affect the performance, so we sent a function into the $apply method and only ran the digest cycle of specific `scope.
Hence, you can $watch the scope whenever you want.
you have a upper case letter in the function name
change this
<button ng-click="myTree.onClick()">456</button>
to this
<button ng-click="myTree.onclick()">456</button>
Demo
angular.module("app",[])
.controller("ctrl",function($scope){
$scope.data = '123';
$scope.$watch('data', function(){
console.log($scope.data);
})
$scope.myTree = {
onclick: function() {
$scope.data = '456';
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<button ng-click="myTree.onclick()">456</button>
</div>

AngularJS - ng-click is calling multiple times

I'm new to AngularJS and have been learning it from W3Schools. My issue is that ng-click is not working properly. It's calling repeatedly. If I click on the element with ng-click once it calls the function once. If I click it again it calls the function twice. If I continue clicking the button the function is called as many times as I've clicked the element before.
<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<h1 id="h12" ng-click="changeName()" style="cursor:pointer;">{{firstname}}</h1>
</div>
<script>
var count = 0;
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.firstname = "John";
$scope.changeName = function() {
var h12 = document.getElementById("h12").innerHTML;
alert(count);
if (count == 0) {
$scope.firstname = "Nelly";
changeNGClick(h12);
count++;
} else {
count++;
var x = "";
var div1 = document.getElementById("h12");
var align = div1.getAttribute("data-v");
alert(align);
$scope.firstname = align;
changeNGClick(h12);
}
}
return false;
});
function compile(element) {
var el = angular.element(element);
$scope = el.scope();
$injector = el.injector();
$injector.invoke(function($compile) {
$compile(el)($scope)
})
}
function changeNGClick(v) {
var el = document.getElementById("h12");
el.setAttribute("data-v", v);
compile(el);
}
</script>
<p>Click on the header to run the "changeName" function.</p>
<p>This example demonstrates how to use the controller to change model data.</p>
</body>
</html>
This is how the code will work. When I click the header which has the text John then it will change to display Nelly. If you click it again it should change back to John. The value will be saved on the <h1> tags data-v. I would also appreciate another way of doing this if you have any suggestions.

Angularjs not updating variables

I want to display/update the calculation answer directly without the need of aditional buttons.
Or do i need a function and button to apply the changes?
<div ng-app="myApp" ng-controller="myCtrl">
A_Number: <input type="number" step="1" ng-model="A_Number"><br>
Display (A_Number): {{A_Number}}
<br>
square: {{square}}
</div>
controller:
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.square = $scope.A_Number * $scope.A_Number;
});
</script>
Make square as a method & use that method in interpolation directive, so that will evaluate on each digest.
Markup
square: {{square()}}
Code
$scope.square = function(){
//made error free
if(!isNaN($scope.A_Number))
return $scope.A_Number * $scope.A_Number;
return 0;
};
Add watch on A_Number to achieve the same. JSFiddle for reference -
https://jsfiddle.net/9a2xz61y/3/
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.square = 0;
$scope.$watch('A_Number', function(newValue, oldValue) {
{
if (!isNaN(newValue)) {
$scope.square = $scope.A_Number * $scope.A_Number;
}
}
});
});

ng-animate not firing event (ng-enter)

I have the following angularjs application which loads content from Instagram, however, on page load I would like to fade the loaded content in with a smooth transition.
For some reason ng-animate doesn't seem to be firing the ng-enter event. so I can add a CSS animation. Is there something wrong?
HTML
<section ng-controller="ShowImages as images" class="page {{ loadedClass }}" >
<div ng-view>
......
</div>
JS
(function(){
//Place your own Instagram client_id below. Go to https://instagram.com/developer/clients/manage/ and register your app to get a client ID
var client_id = '83aaab0bddea42adb694b689ad169fb1';
//To get your user ID go to http://jelled.com/instagram/lookup-user-id and enter your Instagram user name to get your user ID
var user_id = '179735937';
var app = angular.module('instafeed', ['ngAnimate']);
app.filter('getFirstCommentFrom',function(){
return function(arr, user){
for(var i=0;i<arr.length;i++)
{
if(arr[i].from.username==user)
return arr[i].text;
}
return '';
}
})
app.factory("InstagramAPI", ['$http', function($http) {
return {
fetchPhotos: function(callback){
var endpoint = "https://api.instagram.com/v1/users/self/media/liked/";
endpoint += "?access_token=179735937.83aaab0.e44fe9abccb5415290bfc0765edd45ad";
endpoint += "&callback=JSON_CALLBACK";
$http.jsonp(endpoint).success(function(response){
callback(response.data);
});
}
}
}]);
app.controller('ShowImages', function($scope, InstagramAPI){
$scope.layout = 'grid';
$scope.data = {};
$scope.pics = [];
$scope.$on('$viewContentLoaded', function(){
$scope.loadedClass = 'page-feed';
});
InstagramAPI.fetchPhotos(function(data){
$scope.pics = data;
console.log(data)
});
});
})();
I also link to these in the HTML:
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular/angular-route.js"></script>
<script src="bower_components/angular/angular-animate.js"></script>
What am I doing wrong?
See here:
http://machinas.com/wip/machinas/instagramfeed/
Do u ve included the css file right??
I think u don't need this:
$scope.$on('$viewContentLoaded', function(){
$scope.loadedClass = 'page-feed';
});
The ng-enter is active when u set the value of the var that u use inside the ng-repeat
look at this http://codepen.io/shprink/pen/Ariyc

angularjs share data config between controllers

I'm wondering what could be a good way to share directive
between controller.
I've got ie two directives to use in different controller
with different configuration the first think I thought of
using like:
//html
<body data-ng-controller="MainCtrl">
<div class="container">
<div data-ui-view></div>
</div>
</body>
//js
.controller('MainCtrl', function ($scope,$upload) {
/*File upload config*/
$scope.onFileSelect = function($files) {
for (var i = 0; i < $files.length; i++) {
var file = $files[i];
$scope.upload = $upload.upload({
url: 'server/upload/url',
method: 'POST',
data: {myObj: $scope.myModelObj},
file: file,
}).progress(function(evt) {
console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
}).success(function(data, status, headers, config) {
console.log(data);
});
}
};
/* Datepicker config */
$scope.showWeeks = true;
$scope.minDate = new Date();
$scope.open = function($event) {
$event.preventDefault();
$event.stopPropagation();
$scope.opened = true;
};
$scope.dateOptions = {
'year-format': "'yy'",
'starting-day': 1
};
$scope.format = 'MMM d, yyyy';
})
.controller('IndexCtrl', function ($scope) {
})
doing so I can use all the functions in my children controller
but I don't like very much because of collision problems.
Since you cannot use a service (you can't use $scope in a service) the other alternatives could be make an other directive or put the code in a run block
but it's quite the same using a parent controller so
what do you think about ?
UPDATE
what do you think about this approach ?
//outside of angular stauff
function MyTest(){
this.testScope = function(){
console.log('It works');
}
}
//inside a controller
$scope.ns = new MyTest();
//in the view
<p ng-click="ns.testScope()">ppp</p>
RIUPDATE
this seems the best option :)
MyTest.call($scope);
Consider the method described by this post: Extending AngularJS Controllers Using the Mixin Pattern
Instead of copying your methods out of a service, create a base controller that contains those methods, and then call extend on your derived controllers to mix them in. The example from the post:
function AnimalController($scope, vocalization, color, runSpeed) {
var _this = this;
// Mixin instance properties.
this.vocalization = vocalization;
this.runSpeed = runSpeed;
// Mixin instance methods.
this.vocalize = function () {
console.log(this.vocalization);
};
// Mixin scope properties.
$scope.color = color;
// Mixin scope methods.
$scope.run = function(){
console.log("run speed: " + _this.runSpeed );
};
}
Now we can mixin AnimalController into DogController:
function DogController($scope) {
var _this = this;
// Mixin Animal functionality into Dog.
angular.extend(this, new AnimalController($scope, 'BARK BARK!', 'solid black', '35mph'));
$scope.bark = function () {
_this.vocalize(); // inherited from mixin.
}
}
And then use DogController in our template:
<section ng-controller="DogController">
<p>Dog</p>
<!-- Scope property mixin, displays: 'color: solid black' -->
<p ng-bind-template="color: {{ color }}"></p>
<!-- Calls an instance method mixin, outputs: 'BARK BARK!' -->
<button class="btn" ng-click="bark()">Bark Dog</button>
<!-- Scope method mixin, outputs: 'run speed: 35mph' -->
<button class="btn" ng-click="run()">Run Dog</button>
</section>
The controllers in this example are all in the global space and are included in the markup as follows.
<script type="text/javascript" src="lib/jquery.js"></script>
<script type="text/javascript" src="lib/angular.js"></script>
<script type="text/javascript" src="app/controllers/animal-controller.js"></script>
<script type="text/javascript" src="app/controllers/dog-controller.js"></script>
<script type="text/javascript" src="app/controllers/cat-controller.js"></script>
<script type="text/javascript" src="app/app.js"></script>
I haven't tested it, but I don't see why the following wouldn't work:
var myApp = angular.module('myApp', [])
.controller('AnimalController', ['$scope', 'vocalization', 'color', 'runSpeed', function ($scope, vocalization, color, runSpeed) { /* controller code here */}]);
.controller('DogController', ['$scope', '$controller', function($scope, $controller) {
var _this = this;
// Mixin Animal functionality into Dog.
angular.extend(this, $controller('AnimalController', {
$scope: scope,
vocalization: 'BARK BARK!',
color: 'solid black',
runSpeed:'35mph'
}));
$scope.bark = function () {
_this.vocalize(); // inherited from mixin.
}
}]);
see: docs for $controller service
What you want is terrible.
You wouldn't want your controllers to know anything about each other, let alone, one having access to the function of the other. You can just use a Service to achieve that. As for using directives, not sure what exactly you want to happen.
As for your second thing, you can as easily do this
.service('MyTestService', function(){
return {
testScope: function(){
console.log('It works');
}
};
})
.controller('MyController', ['$scope', 'MyTestService', function($scope, MyTestService){
$scope.testScope = MyTestService.testScope;
}])
and in your view:
<p ng-click="testScope()">ppp</p>
I ended up with:
//service
.service('PostUploader',function($upload){
var that = this;
var fileReaderSupported = window.FileReader !== null;
this.notify = null;
this.success = null;
this.showAlert = false;
this.avatar = '';
this.onFileSelect = function($files) {
var $file = $files[0];
var filename = $file.name;
this.avatar = filename;
var isImage = /\.(jpeg|jpg|gif|png)$/i.test(filename);
if(!isImage){
this.showAlert = true;
return;
}
this.showAlert = false;
if (fileReaderSupported && $file.type.indexOf('image') > -1) {
var fileReader = new FileReader();
fileReader.readAsDataURL($file);
fileReader.onload = that.notify;
}
$upload.upload({
url :'/api/post/upload',
method: 'POST',
headers: {'x-ng-file-upload': 'nodeblog'},
data :null,
file: $file,
fileFormDataName: 'avatar'
})
.success(that.success)
.progress(function(evt) {
})
.error(function(data, status, headers, config) {
throw new Error('Upload error status: '+status);
})
};
this.closeAlert = function() {
this.showAlert = false;
};
})
//controller
/* Uploader post */
$scope.dataUrl = null;
$scope.avatar = PostUploader.avatar;
$scope.showAlert = PostUploader.showAlert;
$scope.onFileSelect = PostUploader.onFileSelect;
$scope.closeAlert = PostUploader.closeAlert;
PostUploader.notify = function(e){
$timeout(function() {
$scope.dataUrl = e.target.result;
});
};
PostUploader.success = function(data, status, headers, config) {
$timeout(function() {
$scope.post.avatar = data.url;
});
}
$scope.$watch('avatar',function(newVal, oldVal){
if(newVal) {
$scope.avatar = newVal;
}
});
$scope.$watch('showAlert',function(newVal, oldVal){
$scope.showAlert = newVal;
$scope.dataUrl = null;
});
I did so because I've to do the same thing in create post and edit post but all in all
I've got quite the same repeated code ! :)
The only good thing is the code has got less logic.
obvious but brilliant solution (may be)
(function(window, angular, undefined) {
'use strict';
angular.module('ctrl.parent', [])
.run(function ($rootScope) {
$rootScope.test = 'My test'
$rootScope.myTest = function(){
alert('It works');
}
});
})(window, angular);
angular.module('app',['ctrl.parent'])
.controller('ChildCtrl', function($scope){
});
It's easy and clean and don't see any drawback(it's not global)
UPDATE
'use strict';
(function(window, angular, undefined) {
'use strict';
angular.module('ctrl.parent', [])
.controller('ParentController',function (scope) {
scope.vocalization = '';
scope.vocalize = function () {
console.log(scope.vocalization);
};
});
})(window, angular);
angular.module('app',['ctrl.parent'])
.controller('ChildCtrl', function($scope,$controller){
angular.extend($scope, new $controller('ParentController', {scope:$scope}));
$scope.vocalization = 'CIP CIP';
});
just a little neater and it works CIP CIP :)

Resources