Angularjs list and detail view - angularjs

this is my basic scenario. For a list of items (summary view) i want to show details view of item that got clicked on the same page.
I took this jsfiddle example and transformed it into this jsfiddle. If you look at the behavior it does work for first time but it is not consistent.
Maybe someone can help me with this, or suggest a better approach. I would like to have a different controller for managing the list and a different controller to handle the detail view.

One way of transforming the example (provided that you want to use ngSwitch) would be:
<ul ng-controller="ListController">
<li ng-repeat="item in items" ng-controller="ItemController">
<div ng-click="open(item)">{{item.content}}</div>
</li>
<hr>
<ng-switch on="anyItemOpen()">
<div ng-switch-when="true">
<div ng-controller="ItemController">
{{opened.name}}: overlay: tweet, share, pin
</div>
<a ng-click="close()">close</a>
</div>
</ng-switch>
</ul>
And here is the working jsFiddle: http://jsfiddle.net/pkozlowski_opensource/sJdzt/4/
Your jsFiddle didn't work since you were trying to reference item created in the ngRepeat scope (and thus not available outside of the ngRepeat).

Related

AngularJS Bootstrap UI Typeahead Not Working Properly with Custom Popup Template

I'm working on a .NET MVC application that has some AngularJS pages in it. I'm trying to use Bootstrap UI Typeahead but it's not quite working properly.
If I start to type in the textbox the autocomplete popup opens with potential matches:
However, if I click on one of the matches nothing happens and the underlying angular model is not updated:
The really strange thing is that if I hit tab while the popup is open the first match will get selected and the angular model is updated appropriately:
This is the template I'm using:
<script type="text/ng-template" id="customTemplate.html">
<div class="search-result search-result--mos ng-scope" ng-if="matches.length > 0">
<ul>
<li ng-repeat="match in matches track by $index" class="search-result__item ng-scope uib-typeahead-match">
<div uib-typeahead-match match="match" index="$index" query="query" ng-bind-html="match.model.value"></div>
</li>
</ul>
</div>
This is the relevant front-end code:
<section class="mos intro" data-ng-controller="MosConverterController as vm">
<div>
<form ng-submit="GetCareers()" class="form form--mos">
<div class="form__row">
<div class="form__col form__col--half-plus">
<label for="MOS" class="form__label">MOS/Rate/Duty Title</label>
<input type="text" ng-model="vm.model.SearchTerm" uib-typeahead="career.value for career in vm.model.CareerResults | filter:$viewValue | limitTo:8" typeahead-popup-template-url="customTemplate.html" id="MOS" class="form__input--text" placeholder="Start Typing" name="MOS" required>
<div>Current Search Term: {{vm.model.SearchTerm}}</div>
<textarea>{{vm.model.CareerResults}}</textarea>
</div>
</div>
</form>
</div>
Here's our angular model. Note that we're using Typescript in this project:
import {MosConverterSearchResult} from "../models";
export class MosConverterModel implements Object {
SearchTerm: string = null;
CareerResults: MosConverterSearchResult[];
SelectedCareer: MosConverterSearchResult;
}
I followed the tutorial from the Angular Bootstrap documentation here for the "Custom popup templates for typeahead's dropdown" section but I can't figure out what I'm doing wrong. I'm sure it's something simple but I just can't figure it out. I should note that adding ng-click to the li element like they have in the tutorial doesn't fix the issue. I've tried it like this before:
<li ng-repeat="match in matches track by $index" class="search-result__item ng-scope uib-typeahead-match" ng-click="selectMatch($index)">
<div uib-typeahead-match match="match" index="$index" query="query" ng-bind-html="match.model.value"></div>
</li>
After banging my head against my desk for a couple of hours I figured out the issue was the ng-if in my template. The example in the tutorial link I posted above uses ng-show. ng-if destroys the DOM element and destroys its scope in the process. That's why nothing would happen when I clicked on an item from the list. Not sure why the tabbing would work though if this was indeed the case. If anyone knows please add a comment or better answer.

How to add ngClick to an existing element

So I have some HTML that I do not control.
<div id="myDiv">
Stuff inside my div...
</div>
I want to add an ngClick to it. If I could control the html, I would just do this
<div id="myDiv" ng-click="doSomething()">
Stuff inside my div...
</div>
But like I said, I can't change the html. If this was jQuery, I would just do
$('#myDiv').click(function(){
doSomething();
});
How do I do this in Angularjs? Thanks.
UPDATE
Judging from the downvotes, it seems like you guys are not happy with what I am trying to do here, so let me explain.
I am using AngularUI in my app. AngularUI has all these templates that they insert. For example
<accordion-heading></accordion-heading>
becomes
<div class="panel-heading">
<h4 class="panel-title">
<a href="" class="accordion-toggle" ng-click="toggleOpen()" accordion-transclude="heading">
<span class="ng-binding ng-scope">Heading</span>
</a>
</h4>
</div>
I want to add ngClick to "panel-title". I COULD overwrite the template and add it, but I don't want to do that. Coming from jQuery, it makes sense to just listen to a click event on "panel-title". How it is done Angular? Thanks.
You need to find the element, smth like: angular.element(//selector here); then add attribute you need(ng-click), .attr('ng-click', '//whatever should be here'), and then compile it with angular $compile.
But. I feel sad that you have to do this, I hope you'll find a possibility to change html.
Docs for compile

ng-class within ng-repeat when object comes from other object/array

PLUNKER
I have an app that allows users to see info about live music and favorite the shows they like. Pushing the star button does this. They can then see this information on their own music calendar page.
I'm able to save and update the favoriting data into my database just fine now. But I can't figure out how to style the star buttons (favoriting buttons) based on whether the user has favorited the item or not. They should change color/style if they are favorited or not.
There is data that comes from the music shows and data about the user (their personal info or favorites). These are separate bits of data. So when I bring the shows info in via ng-repeat, this is different than the info I have on whether the user has favorited that show.
The jist of the question, then, is how to style items/icons using ng-class within an ng-repeat when the info on whether those items have been favorited (true or false) comes from another object or array (can create either). Most of the examples with ng-repeat and ng-class are a alot simpler because the data on whether something is selected or not is within that same object.
HTML
<div class="list-group">
<div class="nav nav-stacked list-group-item" id="sidebar" ng-repeat=
"show in shows[0]">
<div>
<div class="col-md-3 text-center">
<h2>{{show.properties.price}}</h2>
<p id="tagtext">{{show.properties.tags}}</p>
</div>
<div class="col-md-6">
<h4 class="list-group-item-heading">{{show.properties.artist}}</h4>
<p class="list-group-item-text">{{show.properties.venue}}</p>
</div>
</div>
<div class="media col-md-3">
<h2 class="fa fa-star-o" ng-click="toggleStarred(show)" ng-class="I don't know">
</h2>
</div>
</div>
</div>
</body>
The pertinent part of the html is around <span class="pull-right star" ng-controller="StarredCtrl"> That's what creates the star icon.
Controller
I'll include the plunker so as not to have to jam this up.
The object where the user favorites are stored looks like this
$scope.loggedInUserFavorites = Object { $$conf: Object, $id: "favorites", $priority: null, show0: true, show1: false, show3: true, show5: false }
using Angular.foreach I pared it down to this:
Object { 0: false, 1: false, 3: true, 5: false }
How can I access those true/false properties of $scope.loggedInUserFavorites on my template to style the star icon?
PLUNKER
Actually this should work:
<h2 class="fa fa-star-o" ng-click="toggleStarred(show)" ng-class="{fillgreen:loggedInUserFavorites[show.properties.id]}">
As scopes prototypically inherit from their parents, you do actually have access to both the show model from the ng-repeat scope, and loggedInUserFavorites from the StarredCtrl scope.
Cheers!
Try this (where shows[$index].starred is your logic to check if the show has been favorited)
<div class="media col-md-3">
<h2 class="fa fa-star-o" ng-click="toggleStarred(show)" ng-class="{starred: shows[$index].starred, no-star: !shows[$index].starred}">
</h2>
</div>
I basically used both #sanghas26 and #HeberLZ's to come up with:
<h2 class="fa" ng-click="toggleStarred(show)" ng-class="{'fa-star': loggedInUserFavorites[show.properties.id], 'fa-star-o': !loggedInUserFavorites[show.properties.id]}"></h2>
So I changed the h2 to fa and then used the full and empty stars as the css classes. I really don't know why fillgreen and fillblue didn't work here. Will continue to investigate.
Anyway, it works. This took 6 weeks to figure out.

How to: Angular Tree?

Hi all you experts out there.
My testing area: http://plnkr.co/edit/ddJT1e4a8L5NTSIVNTk7
I am trying to visualize hierarchical data in a tree-form with Angular, even though i'm using some samples to aid me in my quest (like http://jsfiddle.net/alalonde/NZum5/ and http://jsfiddle.net/brendanowen/uXbn6/8/) i fail.
As soon as i place the recursive element ng-include inside the ng-repeat in side the template it self, the memory usage of its browser-window goes through the roof and effectively hangs the browser. But the available tree-sample i could find are doing just that.
What am i missing?
You need to use the same variable name in the template. The current node is called node in the controller then child in the template.
This cause the template to render the same node over again.
It works fine if you use the same variable name :
<li ng-repeat="node in node.children" ng-include="'node.html'"></li>
See it in action here : http://plnkr.co/edit/mjfdSEDcMK8kGCRjS6V6?p=preview
If anyone here wants to avoid having the extra ng-repeat outside of the template (where it kind of includes stuff from the template anyway), here's a fiddle showing how to do it:
http://jsbin.com/hokupe/1/edit
Also here's a blog post and a 10-15 minutes video on how it works:
http://gurustop.net/blog/2014/07/15/angularjs-using-templates-ng-include-create-infinite-tree/
Sample Code:
<script type="text/ng-template" id="treeLevel.html">
<ul>
<li ng-repeat="item in items">
<input type="checkbox"
name="itemSelection"
ng-model="item._Selected" />
{{item.text}}
<div ng-include=" 'treeLevel.html'"
onload="items = item.children">
</div>
</li>
</ul>
</script>
<div ng-include=" 'treeLevel.html' "
onload="items = sourceItems">
</div>

Angular: Show Form Elements when select is valid after on change shows all hidden form elements in loop instead only the one which select was changed

i repeat things in ng repeat like so
<div class="" ng-repeat="deutscheBankEvent in deutscheBankEvents">
<div class="schrottler-opened schrottler" title="">
<span class="presse_ueber" style="font-size:22px;margin-left:10px;font-weight: normal;margin-top:5px">{{deutscheBankEvent.name}}</span>
</div>
<!-- data-ng-repeat also possible-->
<div class="">
<div class="presse_content">
<Div style="color:white">{{deutscheBankEvent.name}}</div>
<ul class="liste_k">
<li ng-repeat="list in deutscheBankEvent.list">
{{list}}
</li>
</ul>
</div>
</div>
later down the code comes up a form to register to events. the form is hidden until user selects a place and date via select. this is triggered like so:
<span ng-show="myForm.locationDate.$valid">
my issue now is: this shows up all hidden form elements when one select is valid.
how can i set the scope to only this one changed?
Since ng-repeat creates a new scope, changing ng-show/ng-hide conditions to scope bound properties will work perfectly (example).

Resources