Access and bind data outside of ng-repeat - javascript

I have an ng-repeat which repeats a bunch of products in a dropdown.
On hover over these guys, I want to bounce the image that I'm hovering into a container outside of the dropdown.
MARKUP:
<div class="quick-view-filters-container" ng-controller="setZoomDrop">
<!-- zoomed image container from ng-repeat below -->
<div class="product--shade__image-zoom--container">
<img class="ng-hide" ng-show="zoom=1" image="option.product" step="1" always="1" />
</div>
<!-- dropdown -->
<div class="product-select-shades-container" ng-repeat="attribute in attributes | onlyAttrsWithManyOptions | orderBy:$parent.$parent.$parent.configurableOrder">
<h4>Products:</h4>
<div class="product--options_list">
<div ng-repeat="option in attribute.options" class="product--option_item" ng-if="option.product">
<span class="product--shade__image ">
<!-- image -->
<img class="{{:: attribute.code == 'lamp_colour_config' ? 'zoomed' : ''}}" image="option.product" step="1" ng-mouseenter="setZoom(1)" ng-mouseleave="setZoom(0)" always="1" />
</span>
</div>
</div>
</div>
</div>
Controller:
window.app.controller('setZoomDrop', ['$scope', function($scope) {
var zoom = null;
$scope.setZoom = function(number) {
$scope.zoom = number;
};
}]);
Workings:
You can see in the markup that I am setting a variable to 1 or 0 dependable on whether a product in the dropdown is hovered over.
This I have tried to use in the zoomed image container.
option.product in the zoomed image container will not work as I don't know how to pull out the active image from the ng-repeat.

in your setZoom function, instead of passing a number pass the option object if mouseenter or null if mouseleave:
$scope.curOpt = null;
$scope.setZoom = function(option) {
$scope.curOpt = option;
}
Then in your html:
<img ng-show="curOpt" image="curOpt.product" step="1" always="1" />

Related

How activate ng-class only on one element?

I have ng-repeat and ng-class for each element. I use it for selecting elements (add border for selected).
<div class="main-block_channel_create">
<section class="parent_messageList cancelDelete">
<div id="section_animate" class="messagesList_block cancelDelete" infinite-scroll='messagelist.nextSet()' infinite-scroll-listen-for-event='anEvent' infinite-scroll-distance='100'>
<!-- User Images List -->
<a href="" class="messageBl message_preview animated" ng-repeat='preview in messagelist.previewList'>
<div class="image_container_preview" ng-class="{community_select: item.isSelected}" ng-click='communitySelect(preview)' attr="{{preview.preview_id}}">
<img class="deleteMessageBtn" src="images/close_icon.svg" ng-click="deleteMessage(preview.message_id)">
<div class="spinner_container">
<!--<img src="/images/logo-80.svg" class='spinner_img'>-->
<img class="spinner_logo_vertical" src="images/logo_vertical-part.svg" alt="">
<img class="spinner_logo_left" src="images/logo_left-part.svg" alt="">
<img class="spinner_logo_right" src="images/logo_right-part.svg" alt="">
</div>
<img class="message_preview-image" src="{{preview.image}}" alt="">
<!-- Tсли нет изображения — показываем текст -->
<div class="message_preview-text MediumNormalJunior" ng-if="!preview.image">
<div class="message_preview-text-inner" ng-if='preview.name'>
{{preview.name}}
</div>
<!-- если нету и текста показываем empty-->
</div>
<div class="empty_message" ng-if='!preview.text && !preview.image'>
<!--<h4>Empty</h4> -->
</div>
</div>
<div class="stats" ng-show='preview.total_score > 0'>
<p>{{preview.total_score}}</p>
</div>
</a>
<footer class="listFooter">
</footer>
</div>
</section>
sass
.community_select
border: 3px solid white
directive
(function(){
'use strict';
angular
.module('buzz')
.directive('channelcreate', channelcreate);
function channelcreate($rootScope, $location, $timeout, $cookies, $window, communityApiService, getCommunities){
return{
restrict: "E",
replace: true,
scope: true,
templateUrl: '/templates/channelCreate/channelCreate.html',
link: function($scope){
// $rootScope.showChannelCreate = null;
// Select communities for create new channel
$scope.communityList = [];
$scope.communitySelect = function(communityId){
$scope.selected = false;
if ($scope.communityList.indexOf(communityId) == -1){
$scope.communityList.push(communityId);
} else {
$scope.communityList.pop(communityId)
}
console.log($scope.communityList);
};
// all messages preview are loaded from messagesLoadFactory
$scope.messagelist = new getCommunities();
}
};
};
})();
I can identify each div by id when it is clicked. How can I change only one element, but not all of them?
Following your login... an option can be to check if the element's id is in the list of selected elements with communityList.indexOf(preview.id) != -1 so your ng-class would look like:
ng-class="{community_select: communityList.indexOf(preview.id) != -1}"
Edit
Also, when deleting an id from the $scope.communityList make sure you first find its index and then remove it with splice.
Now the portion for removing/adding the id would look like this:
// ... content omitted
$scope.communitySelect = function(communityId) {
$scope.selected = false;
var index = $scope.communityList.indexOf(communityId);
if (index == -1) {
$scope.communityList.push(communityId);
} else {
$scope.communityList.splice(index, 1)
// ^^^ ^
// remove starting_here one_element
}
console.log($scope.communityList);
};
// ... content omitted
I guess you want to keep selection on screen to highlighted, for the same I don't think so you need to maintain extra collection list. Rather you can add flag isSelected on that record and toggle it based on user click.
HTML
I have and ng-repeat and ng-class for each element. I use it for selecting elements (add border for selected).
<a href="" class="messageBl message_preview animated"
ng-repeat='preview in messagelist.previewList'>
<div class="image_container_preview"
ng-class="{community_select: item.isSelected}"
ng-click='communitySelect(preview)'
attr="{{preview.preview_id}}">
</a>
Code
$scope.communitySelect = function(communityId) {
item.isSelected = !item.isSelected;
};
And whenever you need list of selected previews, you can easily loop over the previews collection and grab those ones who have isSelected flag ticked.
var selected = $scope.previews.map(i => i.isSelected);

Target only 1 button in Angular

Im getting the values in a div from the DB and displaying using ng-repeat:
<div ng-controller = "myTest">
<div ng-repeat="name in names">
<h4>{{name.name}}</h4>
<button ng-class="{'active': isActive}" ng-click="test()" >me</button>
</div>
</div>
In my controller I have:
$scope.test= function(){
$scope.isActive = !$scope.isActive;
}
I have defined a class isActive in my css and that is applied/removed to the button on click. There are 5 results so 5 divs are created cause of ng-repeat and 5 buttons(1 for each respective div). The problem is that every button (all 5 of them) is getting that class. I want the class to be applied/removed only to the button clicked. How can I achieve this?
You can try something like this :
<div ng-controller="myTest">
<div ng-repeat="name in names">
<h4>{{name.name}}</h4>
<button ng-class="{ active : name.isActive }"
ng-click="name.isActive = !name.isActive">me</button>
</div>
</div>
Hope this will help.
You need to keep track of each button status.
One way will be to passing the name or anything that uniquely identify the button to your function:
<div ng-controller = "myTest">
<div ng-repeat="name in names">
<h4>{{name.name}}</h4>
<button ng-class="{'active': buttons[name].isActive}" ng-click="test(name)" >me</button>
</div>
</div>
$scope.buttons = {};
$scope.test= function(name){
$scope.buttons[name].isActive = !$scope.buttons[name].isActive;
}
I created a plunk that answers this question without modifying your source array.
Your function becomes
vm.test = function(buttonIndex) {
//Clear the class if you press the same button again
if (vm.buttonIndex === buttonIndex) {
vm.buttonIndex = undefined;
} else {
vm.buttonIndex = buttonIndex;
}
};
And your HTML is
<div ng-repeat="name in main.names track by $index">
<h4>{{name.name}}</h4>
<button ng-class="{'active': main.buttonIndex===$index}" ng-click="main.test($index)">me</button>
</div>

I have a 100 button, click each button to display its corresponding bomb box, With javascript and angular

a button corresponding to a prompt box,each box is different shells;Although implements the desired function, but my code is too complicated, and that there is no simple way. how can I do? This is my code
<--html button-->
button1
button2
...
button100
<--html pop box-->
<div class="note1" style="display:none;">
<img class="title-css" src="note1.png">
<p class="one">note1</p>
</div>
...
<div class="note100" style="display:none;">
<img class="title-css" src="note100.png">
<p class="one">note100</p>
</div>
<--angular js-->
$scope.showRulePop = function(index) {
for(var i=1;i<=8;i++) {
$('.note'+i).hide();
}
$('.note'+index).show();
};
Well first of all, don't use jQuery, unless your in the directive level of angular jQuery have nothing to do there.
First let's get rid of the links part using a simple ng-repeat :
<--html button-->
<div ng-repeat="button in buttons">
{{button.label[i]}}
</div>
// JS in the controller
$scope.buttons = [{
label:'button1'
},{label:'button2'}];
As you can see i declare in the javascript all your buttons and i just loop over it.
Now the "bombox" or whatever it is let's make it a simple template :
<div class="{{currentnote.class}}" ng-if="currentNote">
<img class="title-css" src="{{currentNote.img}}">
<p class="one">{{currentNote.content}}</p>
</div>
// and use ng-repeat for the eight first when there is no button selected
<!-- show 1 to 8 if note current note selected -->
<div ng-repeat="button in buttons1To8" ng-if="!currentNote">
<div class="{{button.note.class}}">
<img class="title-css" src="{{button.note.img}}">
<p class="one">{{button.note.content}}</p>
</div>
</div>
// JS
$scope.buttons = [{
label:'button1'
note:{class:'note1', img:'note1.png', content:'note1'//assuming no HTML or you' ll need something more
}},{label:'button2', note:{...}}, ...];
$scope.showRulePop = function(index){
$scope.currentNote = $scope.buttons[index].note;
}
$scope.buttons1To8 = $scope.buttons.slice(0, 8);//0 to 7 in fact
That's all, no need of jQuery.

Apply $scope ng-click event to hidden element after it is displayed

Please ask me for better explanation. I have built a global search function into the header of my site. I want to display a separate input box for mobile search that uses the same ng-click event but the input isn't displayed when the page loads. I am having trouble getting the hidden input value on the mobile ng-click once it is displayed.
The areas of concentration are the search click function is not finding the correct ng-model when the function is triggered. I think it is because since the hidden elements are not available on load the ng-model="searchQueryStringMobile" isn't applied to the scope somehow.
My question is how do I get ng-model="searchQueryStringMobile" applied in the scope after it has been displayed posthumously or post-click ng-click="flipNav('search')" so that it does not return undefined when you activate the ng-click="loadSearchResults"?
Here is the code:
HTML:
<div ng-controller="HeaderCtrl as header" class="container">
<div id="jesusSearchTop">
<input ng-model="searchQueryString" class="jesusSearchInput autoCompSearch" type="search" placeholder="Search..." autocomplete="off" />
<select ng-model="searchDDL.item" class="jesusSearchSelect" ng-options="item.name for item in searchDDL track by item.id"></select>
<div class="jesusSearchHolder">
<img class="goSearch" ng-model="jesusSearch" ng-click="loadSearchResults('norm')" src="/EMR4/img/gui_icons/searchIcon.png" alt="Search EMR" />
</div>
</div>
<div id="siteControls">
<div id="siteSearch" class="siteControl" ng-click="flipNav('search')"></div>
</div>
<div ng-switch="dd" class="dropDown">
<div ng-switch-when="none" style="display:none"></div>
<div ng-switch-when="search" class="dropMenu listStyle4" id="Search">
<input ng-model="searchQueryStringMobile" class="jesusSearchInput" type="text" placeholder="Search..." autocomplete="off" />
<select ng-model="searchDDL.item" class="jesusSearchSelect" ng-options="item.name for item in searchDDL track by item.id"></select>
<div class="jesusSearchHolder">
<img class="goSearch" ng-model="jesusSearchMobile" ng-click="loadSearchResults('mob')" src="/EMR4/img/gui_icons/searchIcon.png" alt="Search EMR" />
</div>
</div>
</div>
<div class="clr"></div>
</div>
Controller:
app.controller('HeaderCtrl', function ($scope, $http, $location, populateDDL) {
$http.get(badge.credentials[7].home+'data.JSON')
.success(function(data, status, headers, config) {
$scope.header = data.header;
$scope.searchOptions = new populateDDL('tblWebMenuItems',badge.credentials[1].key).
then(function(response) {
$scope.searchDDL = response.tblWebMenuItems
$scope.searchDDL.item = $scope.searchDDL[0];
});
})
.error(function(data, status, headers, config) {
console.log(data+', '+status+', '+headers+', '+config);
});
$scope.flipNav = function(choice){
if ($scope.dd === choice) {
console.log(choice);
$scope.dd = "none";
}else {
$scope.dd = choice;
}
};
$scope.loadSearchResults = function(uv) {
var loader;
if (uv === "mob") {
loader = $scope.searchQueryStringMobile;
}else if (uv === "norm") {
loader = $scope.searchQueryString;
}
console.log(uv+' - '+loader);
if (loader == null || loader < 2) {
alert('Please refine your search and continue, Thank you!');
}else {
$location.path("/search/"+$scope.searchDDL.item.name.toLowerCase()+"/");
$location.search("type",$scope.searchDDL.item.name.toLowerCase());
$location.search("query", loader);
}
};
});
i have tested your code and found that it is because of the ng-switch.As ng-switch creates its own new scope which is child scope of its parent's, so if you use ng-model=$parent.searchQueryStringMobile , then it will work fine or If you use ng-show instead of ng-swtich ,it will work because ng-show doesnt create new child scope, it just sets the markup's css property display to noneand $parent allows you to access items of parent scope from child scope.In your example, $scope.searchQueryStringMobile is in the parent scope of ng-switch's scope. Here is the working plunk click
you can change your ng-switch markup to this
<div ng-switch="dd" class="dropDown" >
<div ng-switch-when="none" style="display:none"></div>
<div ng-switch-when="search" class="dropMenu listStyle4" id="Search">
<input ng-model="$parent.searchQueryStringMobile" class="jesusSearchInput" type="text" placeholder="Search..." autocomplete="off" />
<select ng-model="searchDDL.item" class="jesusSearchSelect" ng-options="item.name for item in searchDDL track by item.id"></select>
<div class="jesusSearchHolder">
<img class="goSearch" ng-model="jesusSearchMobile" ng-click="loadSearchResults('mob')" src="/EMR4/img/gui_icons/searchIcon.png" alt="Search EMR" />
</div>
</div>
</div>
Notice the ng-model for the input element in the above code.
Your problem is quite simple one. ng-switch just like ng-if creates new scope, so when you are using ng-model, yu are assign property to this new scope and not the scope used by your controller.
Solution would be to use controller as syntax or use property of some object created on scope. To illustrate this I create example for you.
As you can see {{a}} does not work outside new scope, but {{x.b}} works just fine.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-init="x = {}; show = 'first'">
<button type="button" ng-click="show = 'first'">show first</button><br>
<button type="button" ng-click="show = 'second'">show second</button><br>
a = {{a}}<br>
x.b = {{x.b}}
<div ng-switch="show">
<div ng-switch-when="first">
<input type="text" ng-model="a">
</div>
<div ng-switch-when="second">
<input type="text" ng-model="x.b">
</div>
</div>
</div>

Angular generating multiple ng-repeats

In my angular application (angular 1.4.9) I have a problem, where multiple ng-repeats are generated when I do this:
HTML:
<div class="form-group col-md-3">
<input ng-model="main.startLocation" ng-change="main.getAddressSuggestions(main.startLocation, 'startLocation')" type="text" class="form-control input-lg" placeholder="fx. Aarhus" tabindex=1 name="country" [![enter image description here][1]][1] />
<label>or select a location from list:</label>
<div ng-repeat="suggestion in main.startLocationSuggestions">
<span>{{suggestion}}</span>
</div>
</div>
controller.js
getAddressSuggestions(address, inputName) {
if (inputName === "startLocation") {
/* var tmpArray = data;
for(var item of tmpArray)
this.startLocationSuggestions = data;*/
this.startLocationSuggestions = ['dada', 'daa'];
}
}
But the generated HTML in the dom is:
Why does angular repeat the ng-repeats?
If you don't want to repeat parent element, here is html:
<div >
<span ng-repeat="suggestion in startLocationSuggestions">{{suggestion}}</span>
</div>
Output will be as:
<div>
<!-- ngRepeat: suggestion in startLocationSuggestions -->
<span ng-repeat="suggestion in startLocationSuggestions" class="ng-scope ng-binding">dada</span>
<span ng-repeat="suggestion in startLocationSuggestions" class="ng-scope ng-binding">daa</span>
</div>
This is how ngRepeat works.
this is basically how the ng-repeat works!
at the start it writes a comment like:
<!-- ngRepeat: x in items -->
then for every element that's been created with ng-repeat, after creating it (WITH the ng-repeat attribite inside), writes another comment:
<!-- end ngRepeat: x in items -->
Because it just takes your template as is (div ng-repeate lalala), clones it N times, fills with data and put into DOM.

Categories

Resources