AngularJS - Getting a ng-repeated DOM element's data model - javascript

This seems super simple. but I can't figure out how its supposed to work.
I have a unordered list of items, which are built from an ng-repeat, which itself is based on a collection of data objects.
So in the DOM (in Jade):
div#projectListing
ul.sidebar-listing
li.sidebar-header Theatrical Projects
li.sidebar-item(ng-click="loadProject()", ng-repeat="project in theatricalProjects | orderBy:'title'") {{ project.title }}
Now I have a nice listing of items in my sidebar, but I want to be able to click one of these elements, and get the full model its tied to - project. What is the 'angular' method to handle this? Do I need to create a custom directive instead of using ng-click()? Do I need to assign an ng-model to each listing with a unique name?
Thanks.

I am assuming you need the respective project inside loadProject when clicked. You could just pass in the project as an argument to loadProject and accept it in your function definition:
li.sidebar-item(ng-click="loadProject(project)", ng-repeat="project in theatricalProjects | orderBy:'title'");
Basically ng-repeat will create a child scope for all the repeated element (li.sidebar) so all of those child scope will have the propery project associated to them and also from inside the method loadProject() you should be also able to access it using this.project

Related

angular onclick events on plain text html elements

New to angular, I have array of responses with below structure
{
type:typeid,
title:"99695 procedure id",
description :"procedure 99265 related to repair of system 56 with combination of 98745 procedure"
}
I need to identify numbers with specific pattern and make them clickable elements[not hyperlinks, better understanding purpose I made hyperlinks here], description field from API response should be formatted like below.
procedure 99265 related to repair of system 56 with combination of 98745 procedure
Using regex I had replaced matching patterns in text with <span style='cursor:pointer'><a>matchednumber</a></span> so subsequently when angular component rendering 'description' field all numbers are getting highlighted as clickable elements.
Problem
I need to register/trigger events like mouse over or click events. How can I bind events on above elements. I tried life cycle methods
ngAfterViewInit on component, ngAfterContentInit on directive
but they need some 'template' to be defined first to get element reference to bind events(correct me if I'm wrong here)
Going through lot of articles/examples but not able to get solve. Can you please suggest how can dynamically register events on 'plan html' content rendering from angular component.

Global Method to Clone object in vuejs rather then reference it, to avoid code duplication

I am building simple CRUD div list with Vuejs, which allows me to perform all operations on single page as search through results by the means of filter.
The problem I face is that in order to do perform update I have to have two containers for each data object in the loop.
So 1st container acts like view, 2nd has the form with same values as view for editing purposes. I basically toggle them to switch from view to edit mode
It looks something like that:
<input v-model="search">
<items v-for="product in products | filterBy search in searchFields">
<item>
<div v-show="!edit">
Display Data "div"
<div>
<div v-show="edit">
Edit Data "form"
<div>
<item>
</items>
I have a problem with using "filterBy" when looping through items to search through them. Because data in 1st and 2nd container is bound upon editing field in edit mode the element disappears. As filter does not care whether the item is in edit mode or in view mode. It simply filters items, and when the value of item is changed and no longer equal to search value its gone.
I have solved the problem by simply cloning object of view element and passed cloned object to form element instead of referencing it by adding objectClone method on child item. Which sort of fixes my problem as the data in edit mode no longer bound to view mode. But this creates another problem, now I have to copy objectClone method on each new child element of the loop in order for this to work. Is there a way to clone element within vuejs without creating a dedicated method or is it possible to create global method objectClone to use it across all Vue elements?
Additional problem I get with my approach is that element after editing now cloned and I cant remove it from parent data container. As it no longer references the previous element that got cloned.

assign custom unique id's to angular directive instances?

I wrote a sliding panel directive and I can't figure out how to have multiple instances of the directive on a page. I am passing in a panel-id attribute to the directive and I need to figure out how to use that id to trigger the correct panel instance. I have a codepen here:
http://codepen.io/mcastre/pen/Ejzebd
Thanks!
What you can do is have the individual directives register themselves with the panelService on link (add a method called registerPanel(scope) to the service for example).
Then your controller methods like toggleWeightPanel() just need to pass in the id that identifies your panel and it can search through the scopes of all registered panels to find the matching one, and call the appropriate method on it.
Somewhere in your controller scope you should keep a list of panel ids that you can use in your ng-click directives and pass down into your panel directives.
Does that make sense?
You really shouldn't need a service for this. A simple true/false param in your code and an ng-show="ShowMe". And in your code set $scope.ShowMe = true;

How to retain the last opened accordion in a group by invoking function in is-open attribute

I'm having accordion which is populated dynamically.
<accordion-group ng-repeat="data in dataList" is-open="isAccordionOpen(data.dataName)">
<accordion-heading>
<span ng-click="openedAccordionGroup(data.dataName)" class="accordionSpan"><b>{{data.dataName}}</b>
</span>
</accordion-heading>
</accordion-group>
Here dataList keep on changing after 15 sec that means I'm populate dataList after regular inteval of 15sec. So i need to persist the last opened accordion group.
DataList can be very hude. So i cant parse and modify it to avoid method invocation in is-open attribute.
In js file, 'm having following code.
$scope.openedAccordionName = '';
$scope.isAccordionOpen = function(name){
return $scope.openedAccordionName === name;
};
$scope.openedAccordionGroup = function(name) {
$scope.openedAccordionName = name;
};
When I'm running it, its giving javascript error.
Error: [$compile:nonassign] Expression 'isAccordionOpen(data.dataName)' used with directive 'accordionGroup' is non-assignable!
What is wrong in above code?
You cannot really do that because angular is looking for a 2-way binding variable that it can assign to. You can easily maintain the last opened by using track by in your ng-repeat. With that what happens is angular will not recreate the DOM element, instead it will just update the existing element's scope which it identify based on what you are tracking by.
Here in the example i have an id for accordions so i am tracking it by id:-
<accordion-group ng-repeat="data in dataList track by data.id" is-open="isOpen">
Plnkr
By default if no track by provided angular will add a unique id $$hashKey for the repeated elements and since you are refreshing as a whole list it will remove the elements from DOM and recreate them. Using track by you will get better performance improvement as well. You can provide any unique key as trackby value (event dataName if it is unique).
In this example you can see that the last accordion is retained opened even if you refresh the data since the isOpen is added on the child scope of repeated element even if you refresh the data if will only update the data based on the id, it wont recreate the accordion.

dynamically add item to angularjs ng-repeat

I have a directive that generates a drag/drop reorderable list with add and remove functionality. If you click in the container, an input is added dynamically, you type in it and when you type a comma, the value you typed is pushed into the list used with ng-repeat to build the list. (Should be kinda familiar to users of this site :) )
This works awesome when the initial object backing it is not null. But when the object begins null and you try to add the first item (by detecting the null and scope.$apply the initialization)the markup is not generated.
Here is a plunk to show what I mean.
http://plnkr.co/edit/Momlgpfy82kHRPwXGR8V?p=preview
In my app, the data is coming from an external source, so I can't ensure non-null lists. How can I get angular to properly respond to the array initialization (and later push)?
Set list to empty array...whenevr a new item is pushed into array angular listeners will update directive
http://plnkr.co/edit/h3GOpTX6Chh1wjcM9QrV?p=preview

Categories

Resources