Getting undefined when i try to access parameter - javascript

I am trying to access the parameter which is passed to the JavaScript function and alert the value. but when i alert the value i am getting undefined in alert. what is wrong i have done here.
html
<div ng-app="plusminusApp" ng-controller="categorylist">
<div class="whitescreen" id="buttons-overlay">
<div class="icons-container">
<div class="icons-inside-container">
<div ng-repeat="category in categories" value="{{category.picture}}" class="category-icon-thumbnail" onclick="setCategory(this.value);">
<img value="{{category.category}}" src="{{category.picture}}">
</div>
</div>
</div>
</div>
</div>
app.js
function setCategory(category){
alert(category)
document.getElementById('buttons-overlay').style.display = 'none';
}

If you want to pass a angular's scope value to a function, it must be ng- prefixed event. You can't pass scope variable to a function outside of angular context.
<div ng-repeat="category in categories" value="{{category.picture}}" class="category-icon-thumbnail" ng-click="setCategory(category.picture)">
and the function must be in the scope of the controller that means you need to define $scope.setCategory = function(val){}

HTML:
<div ng-app="plusminusApp" ng-controller="categorylist">
<div class="whitescreen" id="buttons-overlay">
<div class="icons-container">
<div class="icons-inside-container">
<div ng-repeat="category in categories"class="category-icon-thumbnail" >
<img value="{{category.category}}" src="{{category.picture}}" ng-click="setCategory(category.picture);">
</div>
</div>
</div>
</div>
JS:
$scope.setCategory = function(val){
console.log(val)
}

Assuming this to be your json
$scope.categories = [{
'category': 'ABC',
'picture': 'https://randomuser.me/api/portraits/men/22.jpg'
}, {
'category': 'ced',
'picture': 'https://randomuser.me/api/portraits/men/13.jpg'
}]
Use the below code
$scope.setCategory =function(category) {
$scope.something=category;
document.getElementById('buttons-overlay').style.display = 'none';
}
<div ng-app="plusminusApp" ng-controller="categorylist">
<p>Hello!</p>
<div class="whitescreen" id="buttons-overlay">
<div class="icons-container">
<div class="icons-inside-container">
<div ng-repeat="category in categories" value="{{category.picture}}" class="category-icon-thumbnail">
<button ng-click="setCategory(category.category)"> {{category.category}}
</button>
<img value="{{category.category}}" src="{{category.picture}}">
</div>
</div>
</div>
</div>
</div>
For simplicity and understanding purpose I have changed the click event from div to button.
LIVE DEMO

Related

How to stop all items from being opened when editing item in ngFor loop

I have an array of objects and you can edit the name of each one but then I click to edit one all of the names of the items open, I am wondering how do to fix this.
<div *ngFor="let stop of fave; let i = index" attr.data="{{stop.Type}}">
<div class="card m-1">
<div class="card-body">
<div class="card-text">
<div class="row">
<label class="name" *ngIf="!toggleName" (click)="toggleName = true">{{stop.Name}}</label>
<div class="md-form" *ngIf="toggleName">
<input (keydown.enter)="updateStopName(i, stop.id); toggleName = false" placeholder="Chnage Stop Name" [(ngModel)]="stopName" required mdbInput type="text"
id="form1" class="form-control">
</div>
</div>
<div class="custom">
<img *ngIf="stop.Type === 'Train'" class="train-icon" style="width: 40px; height:40px"
src="assets/img/icon_trian.png" />
<img *ngIf="stop.Type === 'bus'" style="width: 40px; height:40px" src="assets/img/icon_bus.png" />
<img *ngIf="stop.Type === 'Luas'" style="width: 40px; height:40px"
src="assets/img/icon_tram.png" />
</div>
<label class="col-4 custom-label">Stop</label>
<label class="col-5 custom-service-label">Service</label>
<div class="row">
<span class="col-5 stop"> {{stop.StopNo}}</span>
<span style="padding-left:31%;" class="col-6 stop"> {{stop.Type | titlecase}}</span>
</div>
<hr />
<div class="row">
<div class="panel col-7" (click)="getRealtimeInfo({stop: stop.StopNo, type: stop.Type})">
<img class="panel-realtime" src="assets/img/icon_view.png" />
</div>
<div class="panel col-5" (click)="deleteFav(stop.id, i)">
<img class="panel-remove" src="assets/img/icon_remove.png" />
</div>
</div>
</div>
</div>
</div>
</div>
I know its something to do with the index but I am not sure how to write the code to only open the one I clicked on
As you can see at the moment all of them open any help is very much appreciated
If you want to open one at a time, you can use the index and of the item and a boolean. When clicked, set the index value to toggl if it's not already assigned, else assign it null (so that we can close the opened div on same click), and then show the content you want, when toggl === i. Something like:
<div *ngFor="let stop of fave; let i = index">
<label (click)="toggl === i ? toggl = null : toggl = i">Stuff!</label>
<div *ngIf="toggl === i">
<!-- ... -->
</div>
</div>
DEMO: StackBlitz
In your component declare one array
hideme=[];
In your html
<div *ngFor="let stop of fave; let i = index" attr.data="{{stop.Type}}">
<a (click)="hideme[i] = !hideme[i]">show/hide</a>
<div [hidden]="hideme[i]">The content will show/hide</div>
</div>
You have a unique id value inside your array, then you can do it like this:
<div *ngFor="let row of myDataList">
<div [attr.id]="row.myId">{{ row.myValue }}</div>
</div>
Assign an id to your input fields and they will work fine. Right now all of them have same id.
Use this code below as an example:
In your component, create a mapping like so:
itemStates: { [uniqueId: string]: boolean } = {};
Within your on click function:
itemClicked(uniqueId: string) {
let opened: boolean = this.itemStates[uniqueId];
if (opened !== undefined) {
opened = !opened; // Invert the result
} else {
opened = true;
}
}
In your HTML:
<div *ngFor="let item of items">
<h1 (click)="itemClicked(item.uniqueId)">{{ item.name }}</h1>
<div *ngIf="itemStates[item.uniqueId] == true">
<p>This item is open!</p>
</div>
</div>
Essentially, each item in your array should have a unique identifier. The itemStates object acts as a dictionary, with each unique ID having an associated true/false value indicating whether or not the item is open.
Edit: The accepted answer to this question is very simple and works great but this example may suit those who need to have the ability to have more than one item open at once.

How do I find each child that comes after the body element, and get the html of the element with a certain class within it

That might sound a little confusing, but basically I have some html that looks like this (which is dynamically created)
<body>
<div class="component" id="465a496s5498">
<div class="a-container">
<div class="random-div">
<div class="wantThis">
<div class="wantThisHTML">Hello!<p>I'm another element!</p></div>
</div>
</div>
<div class="random-div">
<div class="random"></div>
</div>
</div>
</div>
<div class="component" id="683fg5865448">
<div class="another-container">
<div class="random-div">
<div class="wantThis">
<div class="wantThisHTML">Wow!</div>
</div>
</div>
<div class="random-div6">
<div class="random2"></div>
</div>
</div>
</div>
<div class="component" id="247487294js5">
<div class="more-containers">
<div class="random-div">
<div class="wantThis">
<div class="wantThisHTML">Haha!</div>
</div>
</div>
<div class="random-div6">
<div class="random5"></div>
</div>
</div>
</div>
</body>
And I want to create an array of objects which includes the unique id of the component and the raw HTML within the element with class name "wantThis" (it will always be called "wantThis"), so the array would look like
[{
id: "465a496s5498",
html: "<div class='wantThisHTML'>Hello!<p>I'm another element!</p></div>"
},{
id: "683fg5865448",
html: "<div class='wantThisHTML'>Wow!</div>"
},{
id: "247487294js5",
html: "<div class='wantThisHTML'>Haha!</div>"
}]
As for what i've tried, I split up the elements into an array using var elements = $(body).children, and I know to get the HTML within an element using $(.wantThis).html(), but how can I get the id and the HTML from each of the elements I obtain from the children?
Also, within the wantThis element there may me multiple elements, will $(.wantThis).html() get the raw HTML of ALL the children?
There you go.
var data = $('> .component', document.body).map(function(component) {
return {
id: this.id,
html: $(this).find('.wantThisHTML').html()
}
})
.toArray();
console.log(data);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="component" id="465a496s5498">
<div class="a-container">
<div class="random-div">
<div class="wantThis">
<div class="wantThisHTML">Hello!
<p>I'm another element!</p>
</div>
</div>
</div>
<div class="random-div">
<div class="random"></div>
</div>
</div>
</div>
<div class="component" id="683fg5865448">
<div class="another-container">
<div class="random-div">
<div class="wantThis">
<div class="wantThisHTML">Wow!</div>
</div>
</div>
<div class="random-div6">
<div class="random2"></div>
</div>
</div>
</div>
<div class="component" id="247487294js5">
<div class="more-containers">
<div class="random-div">
<div class="wantThis">
<div class="wantThisHTML">Haha!</div>
</div>
</div>
<div class="random-div6">
<div class="random5"></div>
</div>
</div>
</div>
ONE approach to this is....
Select the Nodes (elements) using "querySelectorAll"
let nodeListOfComponentElements = document.querySelectorAll('.component')
This will get you a NodeList. NodeList
You can turn that into an array of Nodes by:
let nodeArray = [].slice.call(nodeListOfComponentElements) SO-Post
Then, using that array of nodes. You can 'map' it to the structure you want.
let result = nodeArray.map(function(item, index) {
let targetElement = item.querySelector('.wantThisHTML')
return {
id: item.id,
html: targetElement.innerHTML
}
})
note: each "item" is an element/node and the method querySelector can be used to select children of that element. I'm targeting the class you mentioned. Then it's just a matter of returning an object for each iteration that the map function executes. You pick the keys and values that the map function returns. Here I'm setting the id key to the id of the element, and the html key to the "innerHTML" of the target child element within each main element.
The resulting structure is as follows:
(3) [{…}, {…}, {…}]
0: {id: "465a496s5498", html: "Hello!<p>I'm another element!</p>"}
1: {id: "683fg5865448", html: "Wow!"}
2: {id: "247487294js5", html: "Haha!"}
length: 3
CodePen: https://codepen.io/nstanard/pen/exOJLw
Don't forget to upvote and approve my answer it helps!
Thanks
To make sure the .component has wanted '.wantThis' child.
var data = $('.wantThis').map(function() {
return {
id: $(this).parents('.component').attr('id'),
html: $(this).html()
}
});
console.log(data);
var data = $('.wantThis').map(function() {
return {
id: $(this).parents('.component').attr('id'),
html: $(this).html()
}
});
console.log(data);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="component" id="465a496s5498">
<div class="a-container">
<div class="random-div">
<div class="wantThis">
<div class="wantThisHTML">Hello!<p>I'm another element!</p></div>
</div>
</div>
<div class="random-div">
<div class="random"></div>
</div>
</div>
</div>
<div class="component" id="683fg5865448">
<div class="another-container">
<div class="random-div">
<div class="wantThis">
<div class="wantThisHTML">Wow!</div>
</div>
</div>
<div class="random-div6">
<div class="random2"></div>
</div>
</div>
</div>
<div class="component" id="247487294js5">
<div class="more-containers">
<div class="random-div">
<div class="wantThis">
<div class="wantThisHTML">Haha!</div>
</div>
</div>
<div class="random-div6">
<div class="random5"></div>
</div>
</div>
</div>
<div id="elem">
<div id="elem-content">Element</div>
</div>
<script>
alert(elem); // DOM-element with id="elem"
alert(window.elem); // accessing global variable like this also works
// for elem-content things are a bit more complex
// that has a dash inside, so it can't be a variable name
alert(window['elem-content']); // ...but accessible using square brackets [...]
</script>
reference: https://javascript.info/searching-elements-dom

Using AngularJS to show divs based on select value

I'm trying to use an HTML select element's value to show or hide certain div tags with AngularJS. Here is my code:
<body ng-app="kiosk" id="ng-app" >
<div class="page" ng-controller="kiosk-controller" ng-cloak="true">
<section class="signin">
<div class="intro">
<h1 id="service-desk-name">{{servicedeskname}}</h1><br></br>
<h4 id="welcome">{{welcome}}</h4>
</div>
<hr></hr>
<form id="form" name="form">
<div>
<label>Do you have an ID?</label><br></br>
<select type="select"
ng-model="user.affiliated"
ng-required="true"
ng-options="opt as opt.name for opt in affiliate.affiliateOptions">
<option value="">--Select an answer--</option>
</select>
</div>
<div ng-switch="user.affiliated">
<div ng-switch-when="Yes">
<!--><-->
</div>
<div ng-switch-when="No">
<!--><-->
</div>
</div>
And here is the Javascript snippet:
var kiosk = angular.module('kiosk',[]);
kiosk.controller('kiosk-controller', ['$scope', function($scope, $user) {
$scope.servicedeskname = 'Service Desk';
$scope.welcome = 'Please sign in and a consultant will be with you shortly.';
$scope.affiliate = {affiliateOptions:[]};
$scope.affiliate.affiliateOptions = [
{ name: 'Yes' },
{ name: 'No' }
];
/*other stuff*/
};
I can't figure out the proper way to reference the select options in the HTML tags using ng directives. Unless it's not super clear, I want to be able to show one div if the select value is "Yes", and show another if the select value is "No".
I think the switch statement you use need small modification
<div ng-switch on="user.affiliated">
<div ng-switch-when="Yes">
<!--><-->
</div>
<div ng-switch-when="No">
<!--><-->
</div>
</div>
check this ng-switch documentation for more help
I believe you're looking for ng-show and ng-hide.
<div ng-show="user.affiliated === 'Yes'"></div>
<div ng-show="user.affiliated === 'No'"></div>
And try changing this line to this:
ng-options="opt.name as opt.name for opt in affiliate.affiliateOptions">
You forgot the name property in the switch statement.
- <div ng-switch="user.affiliated">
+ <div ng-switch="user.affiliated.name">
As can be viewed in jsfiddle
you just have a little mistake. you must have user.affiliated.name instead of user.affiliated
like this
<div ng-switch="user.affiliated.name">
<div ng-switch-when="Yes">
yes
</div>
<div ng-switch-when="No">
no
</div>
</div>

Selecting only one child element in AngularJS with jquery

So, I had a working function in jQuery but then I decided to use Angular for my application. Just can't find the way so it adds the CSS to only one child element.
Jquery code that was working
$('.list-div').on('mouseenter', function(){
$(this).find('.client-jar').css('opacity','1');
}).on('mouseleave', function() {
$(this).find('.client-jar').css('opacity','0');
});
Current html
<ul>
<li ng-repeat="one in ones | orderBy:'-date'">
<div class="list-div">
<div class="row jar-div first-jar-div" ng-mouseover="showButton()" ng-mouseleave="hideButton()">
<div class="col-xs-7 description-div">
<p class="version">{{ one.version }}</p>
<p class="date">{{ one.date }}</p>
</div>
<div class="col-xs-5 buttons-div">
<div class="list-button client-jar">
<a class="list-link" data-toggle="modal" data-target="#myModal">create server</a>
</div>
<div class="list-button server-jar">
<a class="list-link">Server jar</a>
</div>
</div>
</div>
</div>
</li>
</ul>
And Current Angular JS
$scope.showButton = function(){
angular.element('.list-div').find('.client-jar').css('opacity','1');
};
$scope.hideButton = function(){
angular.element('.list-div').find('.client-jar').css('opacity','0');
};
I would use:
https://docs.angularjs.org/api/ng/directive/ngMouseenter
<button ng-mouseenter="hoverState = true">mouse in mouse out</button>
Then use with:
https://docs.angularjs.org/api/ng/directive/ngMouseleave
<button ng-mouseenter="hoverState = true" ng-mouseleave="hoverState = false">mouse in mouse out</button>
At this point you have a hover over and off flag. You can now pick this flag up with ng-class to set and unset a CSS class which contains your opacity stuff, and any future CSS animations etc etc:
https://docs.angularjs.org/api/ng/directive/ngClass
<button ng-mouseenter="hoverState = true" ng-mouseleave="hoverState = false" ng-class="{'opacity-class':hoverState}">mouse in mouse out</button>
No jQuery required, AngularJS is just a totally different way of going about things.
<style>
.opacity-class .client-jar{
opacity:0;
}
</style>
<ul>
<li ng-repeat="one in ones | orderBy:'-date'">
<div class="list-div">
<div class="row jar-div first-jar-div" ng-mouseenter="hoverState = true" ng-mouseleave="hoverState = false" ng-class="{'opacity-class':hoverState}">
<div class="col-xs-7 description-div">
<p class="version">{{ one.version }}</p>
<p class="date">{{ one.date }}</p>
</div>
<div class="col-xs-5 buttons-div">
<div class="list-button client-jar">
<a class="list-link" data-toggle="modal" data-target="#myModal">create server</a>
</div>
<div class="list-button server-jar">
<a class="list-link">Server jar</a>
</div>
</div>
</div>
</div>
</li>
</ul>
angular.module('App').directive('listFade', function() {
return function(scope, element) {
element.bind('mouseover', function(children) {
// YOUR ANIMATION CODE HERE
});
element.bind('mouseout', function(children) {
// YOUR ANIMATION OUT CODE HERE
});
}
})
then just add the directive to your ng-repeat markup, list-fade=""
you don't need children but its a easy way to call the children of each element. This should help you out. Then get rid of that ng-mouseover showButton();
Updating your code to use inline CSS, would be like this.
var element = document.querySelector('.list-div .client-jar');
$scope.showButton = function(){
angular.element(element).css('opacity','1');
};
$scope.hideButton = function(){
angular.element(element).css('opacity','0');
};
As in AngularJS .element documentation, it's said that you need to pass a element.
You can also use ng-class, creating a class for opacity:
<div class="client-jar" ng-class="{class: expression}"></div>
https://docs.angularjs.org/api/ng/directive/ngClass
Or use ng-show and ng-hide for display control:
<div class="client-jar" ng-show="expression"></div>
https://docs.angularjs.org/api/ng/directive/ngShow
You could even use ng-style for inline css:
<div class="client-jar" ng-style="{'opacity': '1'}"></div>
https://docs.angularjs.org/api/ng/directive/ngStyle

AngularJs ng-repeat does not update after filter object gets updated

Hi I am working on requirement where my filter object is keep getting changed and because of that i have to change ng-repeat on div.
html code :
<div class="col-md-6" ng-repeat="model in models | filter:{ModelText : '!All models', ModelId: '!FilteredModelIds'}:true">
<div class="well">
<div class="media">
<div class="media-object small"><i class="pp-car"></i></div>
<div class="media-body">
<div class="text-box">
<h3>{{model.ModelText}}</h3><span class="hr-small"></span>
</div>
<div class="dashboard-control clearfix">
<div class="simple-metric text-left sub-metric">
<div class="metric-title">Satisfaction score</div>
<div class="metric-number text-red">{{model.SatisfactionAvg}}</div>
</div>
<div class="simple-metric text-left sub-metric">
<div class="metric-title">Total interviews</div>
<div class="metric-number">{{model.TotalInterviews}}</div>
</div>
</div>
<ul class="list-standard">
<li> View interviews</li>
</ul>
</div>
</div>
</div>
</div>
here is the angular js code:
function getModelId() {
dataFactory.getModelIdByFilter($scope.region, $scope.subregion).success($scope.handleSuccess).then(function (result) {
$scope.FilteredModelIds = result.data;
});
}
Model json :
[{"ModelId":0,"ModelText":"All models","Sequence":0,"TotalInterviews":0,"SatisfactionAvg":0.000000},{"ModelId":1,"ModelText":"A3","Sequence":20,"TotalInterviews":2062,"SatisfactionAvg":9.637245},{"ModelId":2,"ModelText":"A4","Sequence":30,"TotalInterviews":3106,"SatisfactionAvg":9.743721},{"ModelId":3,"ModelText":"A5","Sequence":40,"TotalInterviews":1863,"SatisfactionAvg":9.694041},{"ModelId":4,"ModelText":"A6","Sequence":50,"TotalInterviews":280,"SatisfactionAvg":9.642857},{"ModelId":5,"ModelText":"A8","Sequence":70,"TotalInterviews":46,"SatisfactionAvg":11.217391},{"ModelId":9,"ModelText":"Q5","Sequence":110,"TotalInterviews":3176,"SatisfactionAvg":9.503778},{"ModelId":10,"ModelText":"Q7","Sequence":120,"TotalInterviews":1355,"SatisfactionAvg":9.685608},{"ModelId":11,"ModelText":"R8","Sequence":130,"TotalInterviews":31,"SatisfactionAvg":10.064516},{"ModelId":12,"ModelText":"TT","Sequence":140,"TotalInterviews":408,"SatisfactionAvg":9.764705},{"ModelId":13,"ModelText":"A1","Sequence":10,"TotalInterviews":1087,"SatisfactionAvg":10.097516},{"ModelId":14,"ModelText":"A7","Sequence":60,"TotalInterviews":263,"SatisfactionAvg":10.190114},{"ModelId":15,"ModelText":"Q3","Sequence":105,"TotalInterviews":1045,"SatisfactionAvg":9.542583}]
on page load its showing proper data with filter. but on change of filtered object in my case FilteredModelIds, its not getting updated. any help is appreciated.
please let me know if i am worng here.
Thanks.

Categories

Resources