Combining ngClick with ngSwitch - javascript

I know this is a scoping issue, but I can't seem to figure it out. I want to simply change one div into another one by pressing a button. In other words, ng-click will perform the necessary changes for ng-switch to activate.
However, my buttons are both nested within their respective ng-switch-when div so I'm assuming that is the problem.
Here is a fiddle of what I'm talking about: http://jsfiddle.net/gGKGX/8/
Thank you in advance!

In Angular, ng-switch creates a new scope, which means that variables set in a ng-switch constructs aren't accessible outside of it.
In your current scenario as you have defined thingToShow in controller use $parent.thingToShow like
<button ng-click="$parent.thingToShow='two'">Switch!</button>
DEMO

You could have ngClick call a function which updates the thingToShow on the scope.
http://jsfiddle.net/gGKGX/9/
JS:
angular.module("myApp",[]).controller("MainController", function($scope) {
$scope.thingToShow = "one";
$scope.showThing = function (thing) {
$scope.thingToShow = thing;
};
});
View:
<div ng-controller="MainController" ng-app="myApp">
<div ng-switch="thingToShow">
<div ng-switch-when="one">
Showing Thing One
<button ng-click="showThing('two')">Switch!</button>
</div>
<div ng-switch-when="two">
Showing Thing Two
<button ng-click="showThing('one')">Switch!</button>
</div>
</div>
</div>

In addition to the other answers you can use an object value (since things like strings aren't passed through the isolate scope set up by the switch) http://jsfiddle.net/gGKGX/14/
// dom
<div ng-switch="thingToShow.val">
<div ng-switch-when="one">
Showing Thing One
<button ng-click="thingToShow.val = 'two';">Switch!</button>
</div>
<div ng-switch-when="two">
Showing Thing Two
<button ng-click="thingToShow.val = 'one';">Switch!</button>
</div>
</div>
// Ctrl
$scope.thingToShow = {val: "one"};

Related

Apply Changes for <div> using a javascript

This is my div class.
<div class="panel-body relative" ng-attr-id="{{{{$parent.p.cameraId}}}}"></div>
How to replace the "string" of below codes with above ng-attr-id?
var target = document.getElementById('string');
do some code modification
<div class="panel-body relative" id='string' ng-attr-id="{{{{$parent.p.cameraId}}}}"></div>
id='string'
var target = document.getElementById('string').getAttribute('ng-attr-id');
See https://docs.angularjs.org/guide/interpolation#-ngattr-for-binding-to-arbitrary-attributes
<div class="panel-body relative" ng-attr-id="{{$parent.p.cameraId}}"></div>
The value comes from your scope! and gets interpolated. You can't change the view when its already rendered. Because the output of your code will be something like:
<div class="panel-body relative" id="foo"></div>
So that attribute is not there anymore. You have to change your parent scope value. The parent you should be able to reach with a service or so. If you are new with developing and starting with AngularJS personally i would skip that ancient thing and move to Angular.
From your question i see that you want to change things according to the cameraId but then you should simply use views and not mix vanilla JavaScript with Angular.

Two ng-clicks on in same div

So I've been looking around for an answer for this but I just couldn't find the answer. So what I have is a ng-repeat of items that are in a particular class="list-items". When I click on each of the item in items, it should execute a function. Within each list I have an remove button which I would like to remove the item when clicked.
So some code for reference:
<div ng-click="executeCallback($index)" class="list-items">
<div class="item-info">
<span>some info here</span>
</div>
<button ng-click="removeItem($index)">X</button>
</div>
So I did right now, in my CSS, i tried using an position absolute on the button and a z-index of like 10000 to show that it is greater than, but when I click the removeItem button, it still calls the executeCallback function. I don't want it to call the executeCallback function.
Is there a way to have the removeItem function be called only when the remove button is clicked and not the parent class?
You can add multiple events in one ng-click.
<div ng-click="executeCallback($index)" class="list-items">
<div class="item-info">
<span>some info here</span>
</div>
<button ng-click="removeItem($index);$event.stopPropagation()">X</button>
Directives like ngClick and ngFocus expose a $event object within the scope of that expression. The object is an instance of a jQuery Event Object when jQuery is present or a similar jqLite object. Source
You can use this, directly in the HTML template, to stop its propagation by calling $event.stopPropagation(). Just add it on the button and you should be fine:
<button ng-click="removeItem($index);$event.stopPropagation()">X</button>

ng-show, toggle right element on click [Angularjs]

I wana toggle elements but not all elements i need just one on which is clicked.
for example if I have 3 form elements and 3 buttons if I click on button 1. I just wana toggle 1. form element.
This is my current code:
angular:
$scope.formWhat = false;
$scope.formShow = function(item){
$scope.formWhat = !$scope.formWhat;
};
html:
<div ng-repeat="x in comments">
replay
<form id="<%x.id%>" ng-show="formWhat">
blbllblblbl
</form>
</div>
This code will open all forms, but i need just on which is clicked, any idea?
One of the helpful things here is that ng-repeat creates a child scope for each item repeated.
So you can use a local variable inside that child scope that controller knows nothing about. This won't close any of the others but that could be accomplished also. Criteria you gave wasn't very specific
<div ng-repeat="x in comments">
<a ng-click="showForm = !showForm">replay</a>
<form ng-show="showForm"></form>
</div>

Using ng-model (or other solution) without breaking MVC paradigm

I recently asked a question on Stack where I was trying to obtain a DOM element's ID via AngularJS' ng-click. Essentially the answer which was given (with an important caveat was):
Use event.currentTarget vs event.target to get the element to which the binding was registered, BUT this is an atypical way to do it because it ties the controller to the DOM when ideally the controller should know nothing about the DOM.
I'm starting to get a better idea of this now, but would like some further help / clarification.
Using ng-repeat I dynamically render a number of tiles being pulled from a database and present them to the user for selection. When a user clicks on a given tile I want to be able to 'know' that element's ID (or some unique identifier key) so that I can pass it into my javascript / java and then retrieve the details for said key where they are rendered in a different, more detailed view.
I've started to research ng-model which supports the two-way MVC idea, but I'm stuck. You can see below that I'm dynamically rendering each tile with a different ng-model value which equals the tile's database key. Is this the solution I want? If so, how can I reference the ng-model value in javascript? Or if I do that, am I breaking the MVC again? If that's the case, what would be a solution which preserves the model?
Cheers
HTML:
<div ng-repeat="tile in tileResult">
<div ng-model={{tile.id}} ng-click="handleThisElement($event); changeView('panel3')" class="container-fluid btn-default tile">
<div class="row">
<div class="col-xs-9">
<div class="row">
...
</div>
</div>
<div class="col-xs-3 tile-stats">
<div class="row text-center">
...
</div>
</div>
</div>
</div>
</div>
Tie the ng-model to an object, best if it's something in the repeater. Also, ng-model is generally used with an input... not on a div, so I'm not sure what you're trying to achieve here.
You may want to initialize the value to the index (or some other default) if the value doesn't exist, this will avoid null pointers when you want to change the value later.
<div ng-repeat="tile in tileResult">
<div ng-model="tile.someDataValue" ng-init="tile.someDataValue = $index" ng-click="handleThisElement($event); changeView('panel3')" class="container-fluid btn-default tile">
...
</div>
</div>
To later reference the value, you can just access your tileResult object at the appropriate value/index
Ex:
console.log($scope.tileResult[0].someDataValue);
Or you can access the entire 'tile' on click by passing the 'tile' into a function. Ex:
<div ng-model="tile.someDataValue" ng-init="tile.someDataValue = $index" ng-click="someFunction(tile); handleThisElement($event); changeView('panel3')" class="container-fluid btn-default tile">
$scope.someFunction = function(someTile){
console.log(someTile.id, someTile); // log the id, then the entire object
}
If I understand you correctly, you want to be able to access the unique identifier for each tile.
This can easily be done without Ng-Model! One easy fix would be to set the id of each element with the unique identifier:
<div ng-repeat="tile in tileResult">
<div id="{{tile.id}}" ng-click="handleThisElement($event); changeView('panel3')" class="container-fluid btn-default tile">
<div class="row">
This way, when you pass $event to your handleThisElement function, you are able to access the id in the same way you have before.

Observables in Angularjs

I'm doing few exercises to understand how Angularjs work... but I'm a bit confused at the moment...
Following the API, various documentation and tutorials I cannot find exactly what I would like to see...
So I created a small JsFiddle: http://jsfiddle.net/8HqnZ/
What I'm doing is really basic... and probably I'm also doing in a bad way... but I'm learning and every tips will be fantastic for me.
My target here is:
Make everything dynamic... obviously.
I don't understand why if I change name or date on my inputs on top my red bars do not update (seems like it isn't observable...)
I also created a get data button to see my updated Json but it return just [object, Object]...
In plus after I understand these two things I would like to make it inverse as well... I mean something like a draggable red bars that will update date on top... (if it is possible).
Here is my small app:
function App($scope) {
$scope.windows = [
{"name":"First Window","from":"2013-11-05","to":"2013-11-21"},
{"name":"Second","from":"2013-11-10","to":"2013-11-30"},
{"name":"Another One","from":"2013-11-17","to":"2013-11-20"}
];
$scope.addWindow = function() {
$scope.windows.push({"name":"insert name","from":"2013-11-01","to":"2013-11-02"});
};
$scope.setWindow = function(from, to) {
var f = (from.split("-")[2]) * 40,
t = ((to.split("-")[2]) * 40) - f;
return { f: f, t: t };
};
$scope.getData = function() {
console.log($scope.windows);
};
};
The HTML looks like this (I cutted off the "calendar"):
<div ng-app ng-controller="App">
<section id="window-data">
<div ng-repeat="window in windows">
<label>Name:<input value="{{window.name}}"></label> <label>From:<input type="date" value="{{window.from}}"></label> <label>To:<input type="date" value="{{window.to}}"></label>
</div>
<button id="add-window" ng-click="addWindow()">Add Window</button>
</section>
<section id="window-display">
<div id="date-labels">
<div class="block">
<span class="rotate">2013-11-01</span>
</div>
<div class="block">
<span class="rotate">2013-11-02</span>
</div>
...
</div>
<div id="windows">
<div class="window-container" ng-repeat="window in windows">
<span class="window" style="left:{{setWindow(window.from, window.to).f}}px; width:{{setWindow(window.from, window.to).t}}px">{{window.name}}</span>
</div>
</div>
</section>
<button id="get-data" ng-click="getData()">Get Data</button>
</div>
Please if you know good websites with easy and deep documentation, examples, etc... share it with me.
I've always just used the Angular site for documentation. Have you gone through their tutorial?
For your issues: You'll want to use ng-model on those inputs instead of setting the value.
<input ng-model="window.name">
The other issue occurred because you are trying to console.log JSON. You'll need to turn it into a string to log it:
console.log(JSON.stringify($scope.windows));
http://jsfiddle.net/8HqnZ/1/
1.
I don't understand why if I change name or date on my inputs on top
my red bars do not update (seems like it isn't observable...)
To do 2 way data binding you need to use ng-model
Specifically you need to do this
`<input ng-model="window.name">`
instead of input value as "window.name"
I also created a get data button to see my updated Json but it return
just [object, Object]...
This is as expected.
For a draggable, you need to create a custom angular js directive.

Categories

Resources