stop ng-repeat when match ng-if - html

I have an object person like this:
person:
phone:
phone1:
number:"xxx-xxx-xxxx"
checkedSms:true/false
phone2:
number:"xxx-xxx-xxxx"
checkedSms:true/false
smsNumber:""
I have a link <a> I only want to display it under certain condition: either one of the phones checkedSms is true(person.phone.phone[i].checkedSms = true) or smsNumber.length > 0.
I can do the second part by this:
<a ng-click="..." ng-if="person.smsNumber.length > 0"
<div>
...
</div>
</a>
But I don't know how to add the first part, and combine it with the second part above. Tried ng-repeat to repeatly checking on phones of person, but multiple matching results in multiple <a> display. The link should only show once, whenever one condition matches, it should stop further checking.
Hope somebody can help me out. Thanks a lot.

This is how I would do it.
In the HTML:
<a ng-if="checkForSms()" ng-click="...">
In the controller:
$scope.checkForSms = function() {
// code that returns true if the conditions are met
}
Also, I would start using "controllerAs" syntax to prepare for Angular 2.0. https://www.airpair.com/angularjs/posts/preparing-for-the-future-of-angularjs#3-2-remove-dependencies-on-scope

I would create a property in the controller, call it filterPersonList
$scope.filterPersonList = $scope.personList.filter(function (e) {
return e.smsNumber.length > 0 || whatever other condition
})
Then use ng-repeat with the filterPersonList

Related

React: How to provide procedurally generated <li> elements distinct HTML id values?

I'm rendering a map of items retrieved from a database and filtered via the value state of an input field and attempting to then set the state of the input field as the value stored in some list item on click. I figured that using document.getElementById().innerHTML would allow me to retrieve the content stored within the appropriate tag and then set it to state which does work, the issue I'm facing is that it will only retrieve the innerHTML of the first item rendered in the map.
I've tried solutions ranging from applying UUID to making the mapped content available to the window and transfering the state of the individual objects but each disparate solution only moves the value of the first item to state - any ideas?
Rendered Content:
window.filteredItems = this.state.items.filter(
(item) => {
return item.companyNameObj.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1;
}
);
<div className="fixed-width">
<div className="search-container">
<form>
<input type="text" name="search" className="search-bar" placeholder="Search: " onChange={this.handleChange} value={this.state.search} />
</form>
<ul className="search-results">
{window.filteredItems.map((item) => {
return (
<div className="distinct-result-container">
<li key={item.id}>
<div className="image-container">
<img src={item.imageObj} alt={item.companyNameObj + " logo."}/>
</div>
<div className="company-container">
<span onClick={this.stateTransfer}><h3 id={"ID"}>{item.companyNameObj}</h3></span>
<p>Owned by: {item.ownerNameObj}</p>
</div>
</li>
</div>
)
})}
</ul>
</div>
<Footer />
</div>
);
stateTransfer()
stateTransfer(id) {
var search = this.state.search;
var uniqueID = document.getElementById("ID").innerHTML;
this.setState({
search: uniqueID
});
}
The current content of stateTransfer() doesn't represent any significant attempts at approaching a solution to this issue, it's just the minimum required implementation to move the innerHTML content to the input fields value.
EDIT: I've further clarified on the task at hand and a potential solution in the comments below (which follow this), I'm just hoping someone is able to help me with the actual implementation.
#DILEEPTHOMAS The list is comprised of data pulled from a Firebase Realtime Database and is rendered via mapping the filteredList and a search query; that functoionality works fine - what I need is to be able to click the element of any distinct li and have the innerHTML (the text stored in that li's item.companyNameObj) be moved to the value of the input field (so users can navigate the search content with re-typing).
#JoshuaLink I can't necessarily configure the items of the list any
further as it's just data pulled from an external database - I believe
the appropriate solution is to somehow provide a unique HTML ID value
to each newly rendered li and have that selected ID moved to
stateTransfer() where it can be set as the input fields value, I'm
just struggling with the actual implementation of this.
EDIT 2: I've managed to figure out a solution to both parts of the problem as described above - I'll post it as an answer below.
I managed to solve both parts of my problem:
The key issue, which was moving the text stored in each distinct li to the input value, which was apparently easily solved by making my stateTransfer() function accept an event and passing the .innerText value of the h3 through the event (I assumed I would have to use .innerHTML, which would require me to provide each distinct li with a unique generated ID) as follows:
stateTransfer(e) {
var search = this.state.search;
var innerText = e.target.innerText
this.setState({
search: innerText
})
}
The secondary issue, (which I incorrectly assumed was integral to implementing a solution to my question), assigning unique HTML id values to my procedurally generated li's was solved by implementing a for-loop in a componentDidUpdate() function which iterates through the current total length of the list and and assigns an id with the loop iterator concatenated to the end of the string as follows:
componentDidUpdate() {
var i;
var searchCompanyNames = document.querySelectorAll('.comapnyNames');
for(i = 0; i < searchCompanyNames.length; i++) {
searchCompanyNames[i].id = 'companyName-' + i;
}
}
Whilst I didn't need to assign unique ID's to the li's in the correct implementation, it's a useful trick worth noting nonetheless.

PrimeNG p-orderList disable multiple selection of items

I am using PrimeNG's p-orderList. By default, the metaKeySelection attribute is true which implies that a metaKey(ctrl key) is needed to be pressed to select multiple items. I was rather looking for a way to completely disable selection of multiple items. I should be able to select ONLY ONE item in the ordered list.
There is no metaKey attribute available for p-orderList. Can anyone help me with this?
<p-orderList [value]="policyList" [listStyle]="{'min-height':'calc(100vh - 325px)'}" (onSelectionChange)="onSelectionChange($event)">
<ng-template let-policy pTemplate="policy">
<span>{{policy}}</span>
</ng-template>
</p-orderList>
PS: onSelectionChange($event) is triggered every time you select items from the ordered list. $event.value contains the array of the items.
There is no easy flag for it but it can be achieved through calling a function that basically replaces the entire selection array with just the original selected row.
You will need a variable to store the previous value for comparison.
onSelectionChange(event) {
if (event.value.length === 1) {
this.tempValue = event.value[0];
}
else {
event.value = [this.tempValue];
}
}
Can also be simplified by passing event.value to the function
(onSelectionChange)="onSelectionChange($event.value)">
What about the metaKeySelection input property? (as shown here)
<p-orderList [metaKeySelection]="false" [value]="policyList" [listStyle]="{'min-height':'calc(100vh - 325px)'}" (onSelectionChange)="onSelectionChange($event)">
<ng-template let-policy pTemplate="policy">
<span>{{policy}}</span>
</ng-template>
</p-orderList>

Umbraco 7.12: If X Matches Current Page ID, OR Any of Current Page's Descendants - is it possible?

got this snippet ive put together:
#foreach(var item in selection){
if(item.HasValue("location") && #Model.Content.Id == #item.GetPropertyValue<int>("location")){
var singleLink = item.GetPropertyValue<Link>("links");
if(singleLink != null)
{
if(item.HasValue("wideImage"))
{
IPublishedContent mediaItem = item.GetPropertyValue<IPublishedContent>("wideImage");
<div class="owl-item" style="width: 891px;"><img class="tag-headadvert img-responsive" style="display: inline;" src="#mediaItem.Url" width="100%" alt="#singleLink.Name" /></div>
}
}
}
In the second line you can see I make a comparison of the current page ID, vs a variable, is there a way to do, if that variable matches the current page ID, or any descendants of the current page ID?
Thanks
You would need to retrieve the list of Descendant Ids - one of the easiest ways would be to select the Id's from Model.Content.DescendantsOrSelf() - e.g.:
var descendantIds = Model.Content.DescendantsOrSelf().Select(c => c.Id);
Then you can use descendantIds.Contains(#item.GetPropertyValue<int>("location")) in your second line.
Note: if you have a large number of descendants to the current node, you may find you will need to somehow optimise the query, perhaps using caching or come up with an entirely different way of achieving the result you want.

Tally Up Number of Occurrences in Angular

So basically I have this quiz app im working on using angular and I want to tally up the amount of times the right answer is entered. I already made it so the words 'CORRECT' are displayed by the question if they type the right answer in the text box, but I want to see how many times that happens. Here is my code
div ng-repeat="q in questions">
<span>{{ q.question }}</span><br>
<input type="text" ng-model="q.ans" name="email" placeholder="">
<div ng-show="q.ans===q.answer">CORRECT!</div>
<div>
so basically questions is just an array with a question string and answer string. I want to see at the end how many are correct. So I'm thinking, I added in a correct property to the question objects that has a default of 0 which could mean wrong, and change when its right to 1.
Now how would I make it change from the html page here when someone types the right answer? like if correct is shown, if the ng-show is right, then that value would be 1, if not, it'd be 0.
thanks for any assistance. Wondering if I could do this in real time instead of having a 'check' button at the end.
EDIT: okay I looking around the ng-if directive, would it somehow be possible to add like
<div ng-if="q.ans===q.answer">{{ q.correct = 1 }} </div>
or somehow execute that q.correct = 1 (meaning that answer is correct) if the ng-if block is run?
Make a filter for counting the correct answers
// app is your module
app.filter('correctCount', function() {
return function(questions) {
return questions.reduce(function(count, q) {
return count + (q.ans === q.answer ? 1 : 0);
}, 0);
};
})
Then you can display the total in your template
Total: {{questions | correctCount | number}}
Demo ~ http://plnkr.co/edit/br3fxHQ8q04ajZj6Fxch?p=preview
An alternative to reduce that might be easier to understand is...
return questions.filter(function(q) {
return q.ans === q.answer;
}).length;

Dynamic search/filter core-list (Polymer 0.5)

I need to implement a filter-type search which hides items in core list if they do not match the search. I created a .hidden class that is applied to an item if an expression returns false:
class = {{ {hidden: !match(model.host, hQuery)} | tokenList }}
The elements are hidden, but the list does not reflow elements unless I click on a visible row. Is there a way to force a reflow using a function call?
After a week of struggling, hiding list items is just not the right way to handle this. Iterate through the original array, push any matching objects to a temporary array, and then replace core-list's .data array with the temporary array: this.$.list_id.data = tmpArray. Performance is good for lists up to 10K records.
This is what I'm doing in my code, and it works:
<div style="{{hide_part1}}">
...content to show/hide...
</div>
....
Switching it based on route change(flatron-director):
routeChanged: function(oldValue, newValue) {
if ('some_route_1' == this.route) {
this.hide_part1 = ''
this.hide_part2 = 'display: none;'
} else if ('some_route_2' == this.route) {
this.hide_part1 = 'display: none;'
this.hide_part2 = ''
}
},
Also using core-list's updateSize() and especially scrollToItem(0), i.e. back to top, here and there helps as I also had problems with the 'reflow':
https://stackoverflow.com/questions/29432700/polymer-core-list-is-not-rendering-some-of-the-elements