angular ng-class does not react on click - javascript

I am trying to use ng-class and bind a class to an expression so, that I can unit test the expression binding. But, it seems that I am missing something.
The button:
<li><a class="" ng-click="onAddInterface()"><i class="icon-plus-sign"></i> add interface </a></li>
The panel that should collapse and expand:
<div class="collapse" ng-class="{in:showCreateNewInterfacePanel}"><div>
the function that is fired
$scope.onAddInterface=function(){
$scope.showCreateNewInterfacePanel=true;
}
anyway clicking the link nothing happens.
Am I missing something?

I'm not sure if this is how you are really defining your $scope.onAddInterface function or if it is just an example... Nevertheless you should be doing it like this:
$scope.onAddInterface = function() {
$scope.showCreateNewInterfacePanel = true;
}
update
Also make sure the link and the collapsible element are under the same $scope/Controller:
<div ng-controller="Ctrl">
...
<a ng-click="onAddInterface()">add interface</a>
...
<div class="collapse" ng-class="{in:showCreateNewInterfacePanel}"><div>
...
</div>
Controller:
function Ctrl($scope) {
$scope.onAddInterface = function() {
$scope.showCreateNewInterfacePanel = true;
}
}​

I had a very similar problem and was able to solve this problem by placing 'in' in quotes. It is a string, and not a variable.
...
<div class="collapse" ng-class="{'in':showCreateNewInterfacePanel}"><div>
...

Related

Passing parameter to ng-click function with ng-repeat

Please see code below:
<div>
<div class="list-group">
<a class="list-group-item" ng-click="c.selectItem(note.sys_id)"
ng-repeat="note in data.notes">
<h4 class="list-group-item-heading">
{{note.title}}
</h4>
<p class="list-group-item-text">
{{note.sys_id}}
</p>
</a>
</div>
</div>
in the output I can see that note.sys_id is getting printed. However, I need to pass this to the ng-click function on top. I tried below code, but no result:
ng-click="c.selectItem(note.sys_id)"
ng-click="c.selectItem({{note.sys_id}})"
https://jsfiddle.net/1q8mdb3z/
ng-click="c.selectItem(note.sys_id)"
should work for you. Make sure your function is correct. I'd assume your scope is something to the effect
$scope.c = {
selectItem = function(id) {
// do something with id
}
}

How to trigger sibling method in Vue.js

Issue
I can't figure out how to trigger a sibling method in one component
Code
I have a methods like this
methods: {
closeModal: function(){
function closeM(){
$('.modal').css({opacity: 0 , 'visibility':'hidden'});
}
closeM();
},
closeOutside: function(){
$(document).mouseup(function (e){
var container1 = $('.modal__box');
if (!container1.is(e.target) &&
container1.has(e.target).length === 0)
{
this.$emit('closeModal',closeM());
}
});
}
}
my Template
<div class="modal" #click="closeOutside()">
<div class="modal__box z-depth-2 pr">
<div class="modal__header"> {{header}} </div>
<i class="modal__close pa fa fa-times" #click="closeModal() "> </i>
<div class="modal__content">
<slot> </slot>
</div>
</div>
</div>
Question
How to trigger closeModal from closeOutside? I'm new to Vue.js.
In Vue, all your methods will be bound to this, just like any data and computed.
So you can use this.closeModal()
Edit:
I created a fiddle which might help you getting started. Caution: It is a complete rework of your current solution, however it is doing it the 'vue' way.
I am also quite a newcomer to vue, so feel free to improve it.
https://jsfiddle.net/DarkFruits/gr0j9s6x/
this.$emit('closeModal',closeM());
replace with
this.$emit('closeModal',this.closeModal());

Toggle class of parent element using ng-click?

I have some javascript that I'm trying to convert into Angular:
$('.col-lg .fa-clock-o').click(function(e){
$(this).parent().toggleClass('set-time');
e.preventDefault()
});
I've tried adding the following to the child element containing the link, but it doesn't work, maybe theres a proper 'angular' way to do this instead?
A more 'Angular' way to do this would be to set a variable which represents whether or not the set-time class is present on the parent element. By default this would be undefined which is falsy.
Then to toggle it in your ng-click you can just set the value to be the opposite of what it currently is.
<div ng-class="{'set-time': setTimeClass}">
<a href class="fa fa-clock-o" aria-hidden="true" ng-click="setTimeClass = !setTimeClass">toggle class</a>
</div>
Here's a working example:
var app = angular.module('app', []);
.set-time {
background :red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-class="{'set-time': setTimeClass}">
<a href class="fa fa-clock-o" aria-hidden="true" ng-click="setTimeClass = !setTimeClass">toggle class</a>
</div>
</div>
The following works, but not sure its the angular way:
HTML:
Controller:
public toggleTimepickerPopup(event : any) : void{
jquery(event.target).parent().toggleClass('set-time');
event.preventDefault()
}
Parent is not a function, it's a prototype:
Correct usage is:
$(this).parent
And your anchor element:

expression syntax within ng-click

I have 2 variables wkidx and dyidx
I am trying to create multiple collapseable elements on the same page using the angular ui bootstrap directive and I have the following element
<a
href=""
class=""
ng-click="isCollapsed{{wkidx}}{{dyidx}} = !isCollapsed{{wkidx}}{{dyidx}}">
Blah
</a>
now this outputs what I want it to to the dom (ie it appends the variable values to iscollapsed) but I get a syntax error like so
Syntax Error
error in component $parse
Syntax Error: Token 'wkidx' is at column {2} of the expression [{3}] starting at [{4}].
I tried reading the page that the error page links to but it didn't really make things clearer for me. I have tried numerous variations and they either dont give an error but dont append the values or they append the values but throw a syntax error
thankyou for the help here is were I am at but I am getting errors for probably obvious reasons
html
<div
ng-repeat="session in day.sessions"
ng-init="ssnidx = $index">
<a
href=""
class=""
ng-click="setCollapsed(!isCollapsed(wkidx, dyidx), wkidx, dyidx)">
</a>
<div
collapse="I DONT KNOW WHAT SHOULD GO HERE">
<p>hello from the collapsed div</p>
</div>
</div>
app.js
$scope.setCollapsed = function(value, wkidx, dyidx) {
};
$scope.isCollapsed = function(wkidx, dyidx) {
if (isCollapsed + wkidx + dyidx) {
return true;
} else {
return false;
}
};
This is not a valid expression for ng-click. You'd better to create to methods in your $scope:
setCollapsed(value, wkidx, dyidx) and isCollapsed(wkidx, dyidx)
function MyController($scope) {
$scope.setCollapsed = function(value, wkidx, dyidx) {
//...
};
$scope.isCollapsed = function(wkidx, dyidx) {
//...
};
}
<a
href=""
class=""
ng-click="setCollapsed(!isCollapsed(wkidx, dyidx), wkidx, dyidx)>
Blah
</a>
Assuming, that wkidx and dyidx are atached to $scope
Answering to your updated question:
<div
ng-repeat="session in day.sessions"
ng-init="ssnidx = $index">
<a
href=""
class=""
ng-click="setCollapsed(!isCollapsed(wkidx, dyidx), wkidx, dyidx)">
</a>
<div
ng-show="isCollaspsed(wkidx, dyidx)">
<p>hello from the collapsed div</p>
</div>
</div>

AngularJS - change parent scope from directive?

I'm building my first Angular app, but am having a bit of trouble getting something to work. I have a video container that will be hidden until $scope.video.show = true; I'm trying to set this value when I click on a link. I'm trying to make that happen in a directive. Any help would be appreciated.
html:
<div ng-controller="AppCtrl">
<div ng-cloak
ng-class="{'show':video.show, 'hide':!video.show}">
// youtube iframe content, for example
</div>
<div>
<ul>
<li>
<h3>Video Headline 1</h3>
<button type="button"
video-show
data-video-id="jR4lLJu_-wE">PLAY NOW 〉</button>
</li>
<li>
<h3>Video Headline 2</h3>
<button type="button"
video-show
data-video-id="sd0f9as8df7">PLAY NOW 〉</button>
</li>
</ul>
</div>
</div>
javascript:
var thisViewModel = angular.module("savings-video", [])
.controller('SavingsVideoController', function($scope) {
$scope.video = {
show : false,
videoId : ""
};
};
thisViewModel.directive("videoShow", function(){
return{
restrict: 'A',
link: function(scope , element){
element.bind("click", function(e){
var $this = angular.element(element);
$this.closest('li').siblings().addClass('hide'); // hide the other one
$this.closest('li').removeClass('hide'); // keep me open
scope.video.show = true; // doesn't work.
// what is the best way to do this?
});
}
}
});
I see a few things you can improve.
Checkout ngShow/ngHide and ngIf; they'll give you toggle-ability more easily than trying to do it from scratch.
Think in angular. Rather than trying to use logic to modify the DOM on your own, simply setup your rules using angular directives, and let the framework do the rest for you.
For example, it seems like this is more what you want.
<div ng-controller="AppCtrl">
<div ng-cloak ng-show='video.show">
// youtube iframe content, for example
</div>
<div>
<ul ng-switch="video.videoId">
<my-video my-video-id="jR4ABCD" my-headline="Video Headline 1" ng-switch-when="myVideoId" my-video-manager="video" />
<my-video my-video-id="al1jd89" my-headline="Video Headline 2" ng-switch-when="myVideoId" my-video-manager="video"/>
</ul>
</div>
</div>
What I changed is making your iframe show conditionally with ngShow, and using ngSwitch to control which video appears (the appearing video is based on the $scope's video.videoId). Then, I turned your <li>s into a directive called my-video, which ends up looking like this
thisViewModel.directive("my-video", function(){
return{
restrict: 'E',
replace: true,
scope: {
myVideoId = "=",
myHeadline = "=",
myVideoManager = "="
},
template = '<li><h3>{{myHeadline}}</h3><button type="button" ng-click="play()">PLAY NOW 〉</button></li>',
link: function(scope , element){
scope.play = function(){
myVideoManager.show = true;
/*whatever you want here, using scope.myVideoId*/
}
}
}
});
This directive does exactly what your old HTML did, but brings it into the angular framework so you can access the properties you're looking for. By using the raw angular directives, I eliminate the need for any manual UI logic; I don't need to access element at all anymore, and both my HTML and JavaScript are cleaner. There's certainly room for improvement here, even, but I would say that this is closer to the right track.
It takes practice to get more familiar with, but following the guidelines in the SO link above will help.
EDIT
Sorry, think I missed a requirement the first time around. If you want both videos to show when none are selected, don't use ng-switch; just set up some manual ng-shows.
<div>
<ul>
<my-video my-video-id="jR4ABCD" my-headline="Video Headline 1" ng-show="myVideoId == video.videoId" my-video-manager="video" />
<my-video my-video-id="al1jd89" my-headline="Video Headline 2" ng-show="myVideoId == video.videoId" my-video-manager="video"/>
</ul>
</div>
Since ng-switch is really just a shortcut for ng-show anyways, it amounts to the same thing; the logic just got moved into the ng-show attribute instead.
Also, if you have an array of videos, checkout out ng-repeat; it will let you repeat your video tag multiple times automatically, instead of by hand.
<ul>
<my-video ng-repeat='aVideo in myVideoArray' my-video-id='aVideo.videoId' my-headline...(and so on)>
</ul>
Well your controller names don't match up. Try changing AppCtrl to SavingsVideoController.
You only need a very simple solution.
HTML
<div ng-controller="AppCtrl">
<div ng-cloak ng-show="view.show">
<!-- Use ng-show is more convenient -->
</div>
<div>
<ul>
<li>
<h3>Video Headline 1</h3>
<button type="button"
ng-click="view.show = true"
data-video-id="jR4lLJu_-wE">PLAY NOW 〉</button>
<!-- You don't need an extra directive to change view.show -->
</li>
<li>
<h3>Video Headline 2</h3>
<button type="button"
ng-click="view.show = true"
data-video-id="sd0f9as8df7">PLAY NOW 〉</button>
</li>
</ul>
</div>
</div>
JS
var thisViewModel = angular.module("savings-video", [])
.controller('SavingsVideoController', function($scope) {
$scope.video = {
show : false,
videoId : ""
};
};
// No need to create another directive

Categories

Resources