Creating Angular Element Once - javascript

I have an angular page that displays a list of items. It iterates over the list and displays it in a div. Here's the HTML code for that:
<div ng-repeat="item in items">
<div class="item-title-section">
<h1>{{item.text}}</h1>
</div>
<div class="item-special-section"
ng-show="item.type == 'FooB' ||
item.type == 'FooC' ||
item.type == 'FooD'">
<div>
<h2>Speical</h2>
<p>Type Section</p>
</div>
<div>
<span>{{item.text}}</span>
</div>
</div>
</div>
The item-title-section always shows. But I only want the item-special-section to show if the current item is of type B, C, or D. The problem here is if the list contains all 3 items I just want the div to be printed once but the text of each item printed. So in this case:
{
{
type: FooA,
title: FooA,
text: "Some text for this element"
},
{
type: FooB,
title: FooB,
text: "Some text for this element"
},
{
type: FooC,
title: FooC,
text: "Some text for this element"
}
}
The item-special-section div prints twice. Is there a way in angular to statically create an html element, meaning if it's created create it only once?

So one workaround I have figured out for your problem is to allocate the logic for showing only one special item to a separate function attached to the $scope. I have created a Plnkr Example to help demonstrate my explanation.
HTML
<div class="item-special-section"
ng-show="showSpecialSection(item.type)">
<p>I'm a special case!</p>
<p>{{item.text}}</p>
</div>
In the HTML we only allow that element to show if showSpecialSection returns true and we pass in the item.type.
JavaScript
// Define out specialItems
$scope.specialItems = ['FooB', 'FooC', 'FooE'];
// Create an array to stash the first item that fulfills
// the requirement in showSpecialSection
$scope.allowedItem = [];
$scope.showSpecialSection = function(item) {
// First we check if the item is in our defined list
// of special items
if ($scope.specialItems.indexOf(item) != -1) {
// Next depending on if allowedItem has anything,
// we either add it to allowedItem or check if it is
// already inside allowedItem
if ($scope.allowedItem.length == 0) {
$scope.allowedItem.push(item);
return true;
}
else if ($scope.allowedItem.indexOf(item) != -1) {
return true;
}
}
// return false if all other logic checks failed
return false;
}
Please let me know if this works out for you, and comment if you have questions. Cheers ~

Related

Vue.js - Best practice to interpolate data value in console.log object inside methods function?

How can I interpolate text string in nested array to console.log()?
Example:
<template>
<div id="myNavigation">
<div
class="button_link"
v-for="(click) in items"
:key="item.click"
>
<div
class="home-navigation-item-component left-panel selected"
#click="click = menuClickNavigation(click)"
>
{{ item.click }} <!-- Should show the data string -->
</div>
</div>
</div>
</template>
<script>
export default {
data: () => ({
items: [
{ click: 'click one' /* I want this to interpolate to console.log */ },
{ click: 'click two' /* This text string should show when a different element is clicked */ }
]
}),
methods: {
menuClickNavigation (click) {
this.click = (this.items.click)
console.log(this.items.click) /* How to interpolate the items.click value? I want it to display "click one" in the console log function. */
},
}
</script>
Console log displays undefined with current code because it's not interpolating to the desired data value text string in the nested array. Changing the interpolation method (which doesn't currently work because I have no idea how to make it work) with a text string, I get whatever is put in the console.log(), but I want the console.log to interpolate the corresponding text strings in the nested array of items.
Does this make sense?
Aren't you trying to access the value "click" from the items array? I think you should use console.log(this.items[0].click).

Retrieve a select element options list that has been re-ordered with JavaScript

I have a Dictionary of names/numbers that are passed through to my View from my Controller. This becomes:
Model.arrayPositions[x]
These are then added to a select list:
<form>
<div class="col-xs-12">
<select id="ListIn" class="select-width" name="SelectionIn" multiple="multiple" size="#Model.arrayPositions.Count">
#foreach (var item in Model.arrayPositions)
{
if (item.Value != null)
{
<option class="active" value="#item.Value">#Html.DisplayFor(modelItem => #item.Key)</option>
}
}
</select>
</div>
</form>
Array items with no value are ignored, the rest is added to the list.
Items can then be added/removed or moved up/down the list using JavaScript:
function AddSelected() {
$('#ListOut option:selected').each(function (i, selected) {
$('#ListIn').append('<option class="active" value="1">' + selected.innerText + '</option>');
selected.remove();
});
}
function RemoveSelected() {
$('#ListIn option:selected').each(function (i, selected) {
$('#ListOut').append('<option class="inactive" value="-1">' + selected.innerText + '</option>');
selected.remove();
});
function MoveUp() {
var select1 = document.getElementById("ListIn");
for (var i = 0; i < select1.length; i++) {
if (select1.options[i].selected && i > 0 && !select1.options[i - 1].selected)
{
var text = select1.options[i].innerText;
select1.options[i].innerText = select1.options[i - 1].innerText;
select1.options[i - 1].innerText = text;
select1.options[i - 1].selected = true;
select1.options[i].selected = false;
}
}
}
(Moving down is pretty much just the opposite of Moving up)
(#ListOut is simply a second list that has the array items with a value of null added to it)
(The final value is not too important right now, so I'm not specifically retaining it. The order of the list is more important)
I'm changing the order using Javascript to avoid having the page refresh constantly for such a simple action.
However, once I press an update button I'll have a call to my Controller (ASP.NET Core in C#). What I am wondering is how I could retrieve the final values of the list in the new order.
i.e.
If Model.arrayPositions = {a=1,b=2,c=null,d=3}, it would add them to the list as: [a,b,d]
I then use javascript to remove 'a' and move 'd' up, resulting in [d,b]
When I press the update button I would like the retrieve the current list of [d,b] from the View.
What would be the best way to achieve this? Or, alternatively, what other methods might be used to achieve the same goal (note that I wouldn't want page refreshes or partial refreshes if possible).
You can use ajax method to hit your controller on the click of your update button
syntax of jquery ajax is:-
<script>
$.ajax({
type:'POST',
url : 'controllerNAME/ActionNAME',
datatype: 'json',
data : {'parameterOne': parameterone, 'parameterTwo' : parametertwo,...},
success : function(response)
{
alert(response.d)
//put your logic here for further advancements
}
});
</script>

Angular ng-show multiple conditions (no more than 3 work)

I have a div which I need to show when any of 5 conditions are true.
The problem is that ng-show seems to take into consideration only the first 3 conditions. I don't know if it's only my problem, cause I couldn't find any related problem.
In the following example I kept moving conditions around, but each time only the first 3 conditions are taken into consideration. Whatever condition falls into the 4th position, does not show the div.
Please let me know if you know a work around in case it's not possible to have more than 3 conditions.
It's a pretty big div, so I post only a part:
<div class="row " ng-show="selectedAllP[0] || selectedAllF[0] || selectedAllP || selectedAllD || level">
<div class="row selectedCase">
<div><h3 id="choices">Your choices:</h3></div>
<div class="col-md-4" id="publisher">
<h4>Publishers</h4>
<div class="level" ng-hide="selectedAllP[0] || selectedAllP">Select publisher</div>
<table class="table table-bordered table-striped">
<tbody id="pub">
<tr ng-hide="selectedAllP.Name === ' - Any Publisher -'" ng-repeat="roll in selectedAllP" ng-click="deSelectP(roll)">
<td class="deselect">{{roll.Name}}</td>
</tr>
<tr ng-show="selectedAllP.Name === ' - Any Publisher -'" ng-click="deSelectP(selectedAllP)">
<td class="deselect">{{selectedAllP.Name}}</td>
</tr>
</tbody>
</table>
<p ng-show="noticeAnyPublisher && selectedAllP.Name === ' - Any Publisher -'" class="notice">{{noticeAnyPublisher}}</p>
</div>
And the logic for a part of the div above:
$scope.selectedAllP = [];
$scope.setSelectedP = function (publisher) {
$scope.selectedP = publisher.Name;
// Check if the selected publisher is already in the array
// if it isn't, than push it in the array (else do nothing)
if (publisher.Name == " - Any Publisher -"){
$scope.selectedAllP = publisher;
console.log($scope.selectedAllP);
} else if ($scope.selectedAllP.Name == " - Any Publisher -") {
$scope.noticeAnyPublisher = 'Deselect "Any Publisher" first';
console.log("blblblb");
} else if ($scope.selectedAllP.indexOf(publisher) == -1) {
$scope.selectedAllP.push(publisher);
}
console.log($scope.selectedP, $scope.selectedAllP);
};
$scope.deSelectP = function (dePublisher) {
// Check if the selected publisher is already in the array
// if it is, than remove it from the array (else do nothing)
if (dePublisher.Name == " - Any Publisher -") {
$scope.selectedAllP = [];
$scope.selectedP = 0;
$scope.noticeAnyPublisher = '';
} else {
var idx = $scope.selectedAllP.indexOf(dePublisher);
if (idx != -1) {
$scope.selectedAllP.splice(idx, 1);
$scope.selectedP = $scope.selectedAllP[0].Name;
}
}
};
I want when I choose the 4th condition (in this case || selectedAllD) to show the div above, but as u can see, even if the distributor is selected (and selectedAllD exists in console), the div doesn't show. Check next image to see the div showing when I select the 3rd condition (selectedAllF[0]).
div showing when I select the 3rd condition (selectedAllF[0]). It is showing for the fisrt 2 conditions too. Problem is that its behavior is the same, whatever the order of the conditions (it only considers the first 3 conditions).
You could call a method in your ng-show.
<div class="row " ng-show="showRow()">
and declare that function into your .js file.
$scope.showRow = function () {
return $scope.selectedAllP[0] || $scope.selectedAllF[0] || $scope.selectedAllP || $scope.selectedAllD || $scope.level;
}
No matter how many condition you will pass to ng-show or any ohter directive which accepts expressions. See this docs Angular Expressions. So instead, check all of the parts of you condition statement. In such representation it will be evaluated to true every time when there is AT LEAST 1 statement which returns true. Also it is worth to note that this expression will be evaluated from left to right and UNTIL first true statement will be found.

how to display name of a particular code from a javascript object in angular js and html5

I have a angular controller that has the following array which has 3 values.
controller.medicalInstitues;
I want to take the 4th object in the array with code "AUS". Then further, I want to display the name of only 2 medical institutes with the code as "SYD" and "MEL" within that choosen bject from the parent array.
something like below:
var country = select controller.medicalInstitues.countryCode = "AUS"
var institues = select controller.medicalInstitues.name from country.code="SYD" and "MEL";
now I need to bind these in the UI (Angular).
<span class="code"> {{ controller.institutes.name }}</span>
Suppose you have got your list of values in medicalInstitues, then in the angularjs controller you can do
$scope.institues = medicalInstitues.filter(function(value){
return value.countryCode == "AUS" && (value.code == "SYD" || value.code == "MEL");
});
In HTML you can use ng-repeat:
<div controller="controller">
....
<span ng-repeat="institue in institues">{{institue.name}}</span>
....
</div>
In your controller, to bind the 4th object in your array you can set:
$scope.AUS = yourArray[3]
Then in the html you can show the object properties:
{{ AUS."object path to name" }}
Well, if I understood your question well, you can do the following:
// If you have an array that you already know that will come 4 items with the same country code, you can simply do:
$scope.medicalInstitues = array[3];
// Otherwise:
$scope.medicalInstitues = array.filter(function (value) {
return value.countryCode == "AUS";
})[3];
// To get all 'institues' with the countryCode equals to 'SYD' or 'MEL':
$scope.institues = array.filter(function (value) {
return value.countryCode == "SYD" || value.countryCode == "MEL";
});

jQuery - Array element as selector

I created a little script to "like" posts on a certain forum that I frequent, the script works as intended, liking every post on a certain thread.
Now I want to improve it by making it like posts of certain users, rather than every user, so far, I managed to make it work for a specific user:
$(function(){
var TargetLink = $("[data-author='SpecificUser'] span:contains('Like')" );
if (TargetLink.length )
TargetLink.each ( function () {
var clickEvent = document.createEvent ("HTMLEvents");
clickEvent.initEvent ("click", true, true);
this.dispatchEvent (clickEvent);
} );
});
But I can't figure out how to make it work for several users since I'm very new to jquery and javascript, in fact I only started learning it just so I could make this script.
My idea is have an array with user names, make the value of the atribute "data-autor" a variable and then loop the liking function, but I can't figure out how to do it.
The html tree looks something like this:
<li id="post-####" class="message " data-author="User 1">
<div>
<div>
.
.
.
<span class="LikeLabel">Like</span>
.
.
.
<li id="post-####" class="message " data-author="User 2">
<div>
<div>
.
.
.
<span class="LikeLabel">Like</span>
I want to make something like this:
var userNames = ["User1", "User 2", "User 3",...,"User N"];
and then use the elements of the array as the value of the attribute [data-autor='userNames'] in my script, so only post from a specific list of users gets liked, but I have no idea how, I already read several questions but none seem to help me with my specific problem, all the tutorials I find are very basic and doesn't deal with using elements from an array as attribute values.
Try
// do stuff at `click` event
$("span").on("click", function(e) {
// log `user` , `html` of `span` element
console.log($(e.target).parent().data("author"), e.target.innerHTML);
});
// array of user names; note "User 6" does not exist at `html`
var userNames = ["User 1", "User 2", "User 3"
, "User 4", "User 5", "User 6"];
// loop through items within `userNames` array
var links = function links(arr) {
// return a
return $(arr).map(function(i, user) {
// create jQuery object
var TargetLink = $("[data-author='" + user + "'] span:contains('Like')");
// does element, collection exist ?
if (TargetLink.is("*")) {
// if element , collection exists, loop through collection
TargetLink.each(function() {
// do stuff
var clickEvent = document.createEvent("HTMLEvents");
clickEvent.initEvent("click", true, true);
this.dispatchEvent(clickEvent);
})
};
// return `TargetLink` element, collection as jQuery object,
// if user does not exist , will not be included in results
return TargetLink[0]
})
};
console.log(links(userNames));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div data-author="User 1"><span>Like</span>
</div>
<div data-author="User 2"><span>Like</span>
</div>
<div data-author="User 3"><span>Like</span>
</div>
<div data-author="User 4"><span>Like</span>
</div>
<div data-author="User 5"><span>Like</span>
</div>
This Link goes through your options.
I recommend this method.
Query.each:
jQuery.each(substr, function(index, item) {
// do something with `item` (or `this` is also `item` if you like)
});
STACKOVERFLOW
$() accepts an array of strings as a selector, then using your array of users, you can create an array of selectors.
var userNames = ["User1", "User 2", "User 3",...,"User N"];
var selectors = $.map(userNames, function(item){ // this creates a new array
// replace your selector placeholder with the username
var selector = "[data-author='%s'] span:contains('Like')".replace('%s', item);
return selector;
});
users = $(selectors); // Create your jquery object
// Here comes your code...
// Removed the if cause "each" will work even if length is 0
users.each ( function ( ) { // for each matched element
// Simplified your code
$(this).click(); // "this" is the "like"
} );

Categories