Setting div IDs to dynamic IDs using AngularJS - javascript

I am attempting to use Bootstrap accordion to allow a section of text to be expanded upon when a button is clicked. The data is being pulled from a JS file (Angular), however, I cannot seem to figure how how to set the div ID according to the JS file.
HTML:
<li ng-repeat="i in items | searchFor:searchString">
<img ng-src="{{i.image}}" />
<p>{{i.title}}</p>
<button type="button" class="btn btn-desc btn-lg pull-left" data-toggle="collapse" data-target="{{i.id}}">Expand Description/Output</button>
<div id="{{i.id}}" class="collapse">
<p>{{i.desc}}</p>
</div>
</li>
</ul>
Here is the JS:
$scope.items = [
{
id: '1',
url: 'http://google.com',
title: 'Google',
image: 'http://google.com/image.png',
desc: 'Information about Google'
},
{
id: '2',
url: 'http://duckduckgo.com',
title: 'Duck Duck Go',
image: 'http://duckduckgo.com/image.png'
desc: 'Information about Duck Duck Go'
},
I can display properly each entry for url, image, title, but the same application of the {{id}} or {{i.id}} does not seem to work in relation to data-target and div id. I have looked at other Stack items, but cannot seem to work back from them.

firstly:
In your list item you want searchFor to be filter
i.e.
<li ng-repeat="i in items | searchFor:searchString">
should be
<li ng-repeat="i in items | filter:searchText">
secondly:
You can't set an id to an integer, why not try using:
<img ng-src="{{i.image}}" />
This way you have a string which still has your id value. Although your scope sets the int values to string by default, the HTML will render the id as a int not a string, therefore you want to add text into your statement and that way it's more definitive and you avoid the problem of "why isn't my id working?"

Try setting $index of the repeater as the id
<button type="button" class="btn btn-desc btn-lg pull-left" data-toggle="collapse" data-target="{{$index}}">Expand Description/Output</button>
<div id="{{$index}}" class="collapse">

Related

"Filtering the paginated list" is not working on vue-paginate node

in my project i have added the pagination by vue-paginate node, and i added filtering by vue-pagination too and it works fine. When i type in my input field something that does not exist in my list it's blank and thats ok too, but when i start to delete letters nothing shows up on the list, and when i remove all letters the list does not appear, just the pagination appeares.
HTML:
<input class="form-control form-control-search m-input" autocomplete="off" type="text" v-model="search" placeholder="Search...">
<paginate class="m-list-timeline__items no-timeline" name="items" :list="fLangs" :per="10">
<div class="m-list-timeline__item no-timeline" v-for="item in paginated('items')" v-bind:key="item.id">
<span class="m-list-timeline__text">
<span class="timeline-title"><span class="clr-black-light">{{ item.name }}</span></span>
<span class="timeline-subtitle"><span class="clr-grey">{{ item.description }}</span></span>
</span>
<span class="m-list-timeline__time">
<button type="button" class="btn btn-default btn-sm m-btn m-btn--icon m-btn--icon-only m-btn--pill" #click="fetchAndUpdateItem(item.id)"><i class="la la-pencil"></i></button>
<button type="button" class="btn btn-default btn-sm m-btn m-btn--icon m-btn--icon-only m-btn--pill" #click="fetchAndRemoveItem(item.id)"><i class="la la-trash"></i></button>
</span>
</div>
</paginate>
<paginate-links for="langs" :hide-single-page="true"></paginate-links>
Data:
data: function () {
return {
search: '',
paginate: ['langs'],
langs: ['Item One', 'Item Two', 'Item Three', 'Item Four', 'Item Five', 'Item Six', 'Item Seven', 'Item Eight', 'Item Nine', 'Item Ten', 'Item Eleven', 'Item Twelve', 'Item Thirteen']
}
},
Computed:
computed: {
fLangs () {
const re = new RegExp(this.search, 'i')
return this.langs.filter(item => item.match(re))
}
}
Picture before search:
Picture after search and deleting letters:
Don't know why my list is now showing up when i delete the letters, or start deleting it. Can anyone help me please? Thanks.
Thanks to our comment thread, we know that the paginate component isn't rerendering, for whatever reason. I'm not sure what would cause this, but what you can do is to set the :key to something that you know will change with the search value - the easiest thing being to set it to this.search, which, conveniently, is also a primitive.
So you can force the paginate component to rerender by setting the :key like so:
<paginate ... :list="fLangs" :key="search">
However, a better solution would probably involve debugging why the component isn't rerendering - perhaps it's a bug with vue-paginate, perhaps you're not using the component as it's intended (though this seems unlikely since the docs themselves use much the same code). Either way, setting the key on the paginate component should at least get you over this hurdle for now.

List.js - clickable links

My List.js implementation is creating what appear to be links but they're un-clickable. In the image I attached everything appears correct, however the link doesn't work even though when you hover it even underlines like a normal link would. What am I missing here?
I read somewhere that <li> items cannot be assigned href tags? If that is true then how does one get around that little issue?
Javascript:
<script>
var options = {
valueNames: [ 'title', 'description', 'lat', 'lng', 'user_sub', 'location', 'imageurl', 'final_url' ],
item: '<li id="my-list"><h3 class="title"></h3><p class="description"></p><p class="location"></p><p class="user_sub"></p><a class="final_url"></a></li>'
};
var values = JSON.parse('{{ jsonout|safe }}');
var userList = new List('places', options, values);
</script>
HTML:
<div id="places" class="container">
<input class="search" placeholder="Search" />
<button class="Find" data-sort="title">
Search
</button>
<button id="click_me" class="sort" data-sort="location">
Sort by State
</button>
<button id="click_me" class="sort" data-sort="title">
Sort by Name
</button>
<ul class="list"></ul>
</div>

get bound data on click event

This is my Razor Page containing multiple divs with each div containing either follow or unfollow button with NeighbourhoodName and other stuff.
<p class="lead" style="display: none" data-bind="visible: profiles().length == 0">No neighbourhood found...</p>
<ul data-bind="visible: profiles().length > 0, foreach: profiles">
<li class="media" style="border-top: solid 1px lightgrey; padding-top: 15px;">
<div class="media-body">
<h4 class="media-heading">
<a class="btn pull-right" data-bind="visible: !IsFollowed, attr: { href: followAction }">Follow</a>
<a class="btn btn-danger pull-right" data-bind="visible: IsFollowed, attr: { href: unfollowAction }">Unfollow</a>
</h4>
<em data-bind="text: NeighbourhoodName"></em>
<em data-bind="text: NeighbourhoodId"></em>
//stuck at this line
</div>
</li>
I want to Generate a new page with click on any of the div. So,I want to send id of the neighbourhood to action method with click on respective div. Right now, i am able to get NeighbourhoodId with data-bind attribute but dont know how to send this id to action method with click on any area of div means how to mix this anchor tag. something like that.
This is my follow action url in a knockout code which send neighbourhoodId on follow button click:
self.followAction = location.protocol + "//" + location.host + '/Neighbourhood/Follow?uid=' + data.NeighbourhoodId;
But, i dont want any button. simple click on div should send id to action method.
how to achieve this. please suggest me something.
You simply have to use the click binding on the div, and bind it to a function in your viewmodel.
The function in your viewmodel receives as parameter the knockout context available in the bound element. So, you can directly access the desired data from that function.
<div class="media-body" data-bind="click: yourViewModelFunction">
In your viewmodel, your function should be implemented like this:
yourViewModelFunction = function(data) {
// here you can use data.NeighbourhoodId
}

angular change class by id

I have collection in angular. the collection looks like:
$scope.collection = [{id:'a1', title:'title 1'}, {id:'a2', title:'title 2'}];
<span ng-repeat="c in collection" id="{{c.id}}">{{c.title}}</span>
it is then itterate using ngRepeat in a span tag. in other line i have buttons that have custom property, let say data-span-id, like so:
<button type="button" data-span-id="a1">
<button type="button" data-span-id="a2">
when that buttons clicked, i want to change the class of the span that have id equal to data-span-id property. in jQuery
$('#'+$(this).data('span-id')).addClass('someclass');
how to this in angular? PS: spans and buttons is scallable.
It's hard to answer without seeing more of your code, but something along these lines is how I'd do it....
<button ng-repeat="item in collection" ng-click="selected = item.id">{{ item.title }}</button>
<span ng-repeat="item in collection" ng-class="{ 'someClass': selected == item.id }">{{ item.title }}</span>
So clicking a button sets a variable in the scope to the id you want, and then your span checks for that variable to set a class.

How to filter a list in AngularJS using several links

I have been going over a lot of tutorials on how to filter a list and can't find an example for my simple use-case.
I have several buttons such as
Name
Age
Height
I have var persons = {...} object and I display it like
<div ng-repeat="person in persons">
{{person.name...}}
</div>
How do I create a filter so each time I will click on one of the buttons the list will be filtered ?
I have tried addingng-repeat="person in persons | filter:filterPersons"
and on the script side to write:
$scope.filterPersons(person){
if (person.name == "John")
return person;
}
but this is only one use-case (how can I filter by another name?) - in other words - How do I connect the links to the filter?
You can bind your filter to scope variables as you do with any other thing. So all you need is to set the appropriated filter to the scope when the user click and bind it to the ng-repeat filter param. See:
<div ng-app>
<span ng-click="myFilter = {type: 1}">Type 1</span> |
<span ng-click="myFilter = {type: 2}">Type 2</span> |
<span ng-click="myFilter = null">No filter</span>
<ul ng-controller="Test">
<li ng-repeat="person in persons | filter:myFilter">{{person.name}}</li>
</ul>
</div>
function Test($scope) {
$scope.persons = [{type: 1, name: 'Caio'}, {type:2, name: 'Ary'}, {type:1, name: 'Camila'}];
}
Notice that the myFilter is changed when the user clicks the filter, and that it's bound to the ng-repeat filter. Fiddle here. You could also create a new filter, but this solution is far better.
My response is very similar to Caio's. I just wanted to show how to filter out an existing array.
In my ng-repeat I have a search filter that goes through the words. I wanted tabs to look for a string match. So I added a additional filter
<tr class="unEditableDrinks" ng-repeat="drink in unEditableDrinkList | orderBy:'-date'|limitTo:400|filter:search |filter:myFilter">
<td>[[drink.name]]</td>
I only have the top part of my table but this should show the strategy. The second filter called myFilter is attached to the buttons below.
<div class="btn-group" role="group">
<button type="button" class="btn btn-primary" ng-click="myFilter={name:'soda'}">Soda</button>
</div>
<div class="btn-group" role="group">
<button type="button" class="btn btn-primary" ng-click="myFilter={name:'energy'}">Energy Drinks</button>
</div>
On each button I am able to add a ng-click that goes through myFilter and searches the td with drink.name. In each ng-click I can set the value of name to search. So every title containing soda or energy can be filtered through.

Categories