How to set default session and dropdown values in meteor? - javascript

I have a collection which store default values according to the logged in user. I have a setting menu where default can be set for the application by the user. How can we set the dropdown of that setting menu to the default value set previously by user every time and how can we set the default session value. I'm using semantic UI and isron router, I'm trying to get the default values from the collection in .onRendered(), but the output will be Values:
Template.header.onRendered (function(){
var defaultSettingValues=defaultSetting.find().fetch()
console.log ("Values: "+defaultSettingValues);
});
The dropdown in settng menu:
<div class="ui selection dropdown button" id="defaultDrop" tabindex="0">
<input type="hidden" name="filter">
<div class="default text">Select from here</div>
<i class="right floated dropdown icon"></i>
<div class="menu" tabindex="-1">
<div class="item" data-value="objId1">abc</div>
<div class="item" data-value="objId2">def</div>
<div class="item" data-value="objId3">hij</div>
</div>
</div>
I'm trying to get the default setting values from collections and then set the session and set the default dropdown.
How can i solve this? or is there any alternate way in which i can achieve this?

Ok so you can set default value of your dropdown with the following code :
Template.header.onRendered (function(){
// Care because it returns an array, and you just need the default value
var defaultSettingValues=defaultSetting.find().fetch();
// Supposing the defaultSettingValues is equals to 'objId1'
$('#defaultDrop').dropdown('set selected', defaultSettingValues);
});
You need to find a way to get your value from what's returning your collection.

I think you should be using helpers in order to achieve this in a good way.
In the Html template
<template name="The_template">
<div class="ui selection dropdown button" id="defaultDrop" tabindex="0">
<input type="hidden" name="filter">
<div class="default text">Select from here</div>
<i class="right floated dropdown icon"></i>
<div class="menu" tabindex="-1">
{{#each option in options}}
<div class="item" data-value="objId1">{{option.someData}}</div>
{{/each}}
</div>
</div>
</template>
Then in the javascript template
Template.The_template.helpers({
options() {
return Collection.find();
}
})

Related

Problem trying to select next item in JQuery

I'm trying to select the next element to add the class image-radio-selected with JQuery.
My html is like
<div id="photocall">
#foreach ($photocalls as $photocall)
<div class="d-inline-block mx-1">
<div style="background-image: url('')" class="photocallThumb image-radio-selected"></div>
</div>
#endforeach
<input>
</div>
Im trying to:
$( "#mybutton" ).on("click", function() {
var selected = $('.photocallThumb.image-radio-selected'); // working
selected.next('.photocallThumb').addClass('image-radio-selected'); // not working
});
After 2 hours, trying to solve, reading doc,
I'm more confused than when I started...
what am I doing wrong?
One method is you will need to get out of the parent div, then do a next for the parent.
$( "#mybutton" ).on("click", function() {
var selected = $('.photocallThumb.image-radio-selected');
selected.parent(".d-inline-block").next(".d-inline-block").find('.photocallThumb').addClass('image-radio-selected'); // not working
});
.image-radio-selected{border:1px solid #ff00aa;}
.mx-1{width:100px;height:100px;border:1px solid #000000;}
.d-inline-block{display:inline-block;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="photocall">
<div class="d-inline-block mx-1">
<div style="background-image: url('')" class="photocallThumb image-radio-selected"></div>
</div>
<div class="d-inline-block mx-1">
<div style="background-image: url('')" class="photocallThumb"></div>
</div>
<div class="d-inline-block mx-1">
<div style="background-image: url('')" class="photocallThumb"></div>
</div>
<div class="d-inline-block mx-1">
<div style="background-image: url('')" class="photocallThumb"></div>
</div>
<button type="button" id="mybutton">next</button>
</div>
JQuery's next method selects the next sibling of the selected element. However, since your photocallThumb div is inside a d-inline-block div, it has no siblings. You'd have to go back up a level, then find the next photocallThumb, maybe something like selected.parent().find('.photocallThumb').eq(0).
However, an even better pattern that will help you avoid bugs like these is called templating. Basically, on the client side, you have an html template string, and you pass it data that represent your current state. In your case, you'd pass it an array of javascript objects, each one with an image url and an isSelected boolean. Then, when your state changes, instead of using jquery to try to fix what's changed, you just rerender your template and replace your html element's content with the newly rendered template, and it's now magically in the correct state. This is the pattern favored by large frameworks like React and Angular.
Here's an example from lodash that renders a list of usernames:
// Use the "evaluate" delimiter to execute JavaScript and generate HTML.
var compiled = _.template(
`<% _.forEach(users, function(user) { %>
<li><%- user %></li>
<% }); %>`);
compiled({ 'users': ['fred', 'barney'] });
// => '<li>fred</li><li>barney</li>'

semantic ui dropdown items with images using remote data

I'm having trouble populating a dropdown
The code below works fine
<div class="ui multiple search selection dropdown"
style="width: 100%;"
id="list_id" >
<input name="name" type="hidden">
<i class="dropdown icon"></i>
<div class="default text">Lists</div>
<div class="menu">
<div class="item" data-value="{{value.value}}">
<img class="ui avatar image" src="{{value.img}}">{{value.label}}</div>
</div>
</div>
but dont know how to do the same using remote data
I have already tried the apiSettings.onResponse etc methods but not sure what format to return the data in. I also confirmed using successTest that response is the same as I am retuning and onSuccess gets called too. But, nothing shows up in dropdown.
I had the same issue, this is the way I solved it:
let dropdownValues = [];
types.forEach(type =>{ //populating dropdownValues
let value = {};
value.value = type;
value.name = `<image class="ui mini image" src="/resources/${type}.png" />${type}`
dropdownValues.push(value);
})
$('.ui.dropdown').dropdown({
values: dropdownValues
})
As you can see it works like you intented: result

Retain scroll position when a button is toggled

I am working on an angularJS application which has a page where I display around 30 items using ng-repeat. In front of each item, there is a toggle button (enabled/disabled). With the current code that I have, I can toggle these items. But the problem is if I scroll down and toggle lets say item 25, then automatically it scrolls to the top of the page. If I now scroll down, I can see that the toggle actually took place.
So the requirement now is to make sure that the scroll position is retained after the toggle button is clicked.
Please see below the code that I have.
HTML
<div id="eventTypes" class="panel-body">
<div ng-if="!spinner" ng-repeat="item in items" class="panel-body">
<div class="row">
<div class="col-md-9">{{item.itemName)}}</div>
<div class="col-md-3">
<input id="toggleEnabled"
type="button"
ng-class="{'btn-primary': item.enabled}"
value="{{item.enabled ? 'enabled' : 'disabled'}}"
ng-click="toggleEnabled(item)">
</div>
</div>
</div>
<div ng-if="spinner" class="spinner">
<div class="spinner-container container1">
<div class="circle1"></div>
<div class="circle2"></div>
<div class="circle3"></div>
<div class="circle4"></div>
</div>
<div class="spinner-container container2">
<div class="circle1"></div>
<div class="circle2"></div>
<div class="circle3"></div>
<div class="circle4"></div>
</div>
<div class="spinner-container container3">
<div class="circle1"></div>
<div class="circle2"></div>
<div class="circle3"></div>
<div class="circle4"></div>
</div>
</div>
</div>
JS
(function () {
'use strict';
angular.module('myApp').controller('itemsController', function ($scope, itemsService) {
var serviceError = function (errorMsg) {
console.log(errorMsg);
$scope.turnOffSpinner();
};
$scope.items = [];
$scope.item = {};
$scope.spinner = true;
$scope.toggleEnabled = function (item) {
$scope.turnOnSpinner();
itemsService.toggleEnabled(item)
.then(function () {
$scope.loaditems();
});
};
$scope.loaditems = function () {
itemsService.getitems().then(function (response) {
$scope.items = response.data;
}, serviceError);
$scope.turnOffSpinner();
};
$scope.turnOnSpinner = function () {
$scope.spinner = true;
};
$scope.turnOffSpinner = function () {
$scope.spinner = false;
};
$scope.loaditems();
});
}());
How this works right now is, once I click the toggle button, a spinner is enabled. Meanwhile the controller will call the itemService.toggleEnabled() method which does an ajax call to the server to just change the status of the item(enabled to disabled or vice-versa) in the backend. On successful change of the status and when the ajax call returns, the $scope.loadItems() method is called in the controller. This method will then do another ajax call to fetch the items (now with the updated status of the item that was toggled). The spinner is disabled and the data is then displayed on the UI.
When all of this is done, the page is scrolled to the top. This is annoying when I want to toggle an item which is way down in the list.
I want the page to be present at the same position when I clicked the toggle button of the corresponding item and not scrolling up to the top.
I am new to AngularJS and any help in this regard would be really helpful.
It looks like your spinner scheme is what's causing you problems:
...
<div ng-if="!spinner" ng-repeat="item in items" class="panel-body">
...
<div ng-if="spinner" class="spinner">
...
Whenever you click your button, you are removing every single element in your ng-repeat from the DOM when you $scope.turnOnSpinner(). That's why it appears to jump to the top. It's not really jumping, there just aren't enough DOM elements to fill up the page, making the page so short that the scrollbar disappears (even if it's only for a second). Then when the spinner is done, your ng-repeat fills up the page with DOM elements again, resulting in your scroll position being lost.
So basically what you are trying to fix is a symptom of a less than ideal loading spinner implementation.
ng-if is a "brutal" way of hiding things in Angular. It's mostly meant to hide things for a longer period of time than "softer" directives like ng-show/ng-hide. One solution to your problem is to use ng-disabled on each one of your buttons to prevent the user from interacting with it while the spinner is active, rather than doing a hard removal of each element:
Before:
<div ng-if="!spinner" ng-repeat="item in items" class="panel-body">
<div class="row">
<div class="col-md-9">{{item.itemName)}}</div>
<div class="col-md-3">
<input id="toggleEnabled"
type="button"
ng-class="{'btn-primary': item.enabled}"
value="{{item.enabled ? 'enabled' : 'disabled'}}"
ng-click="toggleEnabled(item)">
</div>
</div>
</div>
After:
<div ng-repeat="item in items" class="panel-body">
<div class="row">
<div class="col-md-9">{{item.itemName)}}</div>
<div class="col-md-3">
<input id="toggleEnabled"
ng-disabled="spinner"
type="button"
ng-class="{'btn-primary': item.enabled}"
value="{{item.enabled ? 'enabled' : 'disabled'}}"
ng-click="toggleEnabled(item)">
</div>
</div>
</div>
Another solution, which I really like and use myself is this Angular module: https://github.com/darthwade/angular-loading
You can attach it to any element in the page and it will put a loading spinner over it and prevent you from interacting with it until your ajax or whatever is done.
If you don't like either of those, try putting your ng-repeat into a container that you can use to prevent interaction with your elements when the spinner is up:
<div class="container" ng-class="{'you-cant-touch-this': spinner}">
<div ng-repeat="item in items" class="panel-body">
<div class="row">
<div class="col-md-9">{{item.itemName)}}</div>
<div class="col-md-3">
<input id="toggleEnabled"
type="button"
ng-class="{'btn-primary': item.enabled}"
value="{{item.enabled ? 'enabled' : 'disabled'}}"
ng-click="toggleEnabled(item)">
</div>
</div>
</div>
</div>
Now you can style it in some way to prevent interaction without having to remove all those items from the DOM:
.you-cant-touch-this {
pointer-events: none;
}

Ember JS Enable dropdown only on element which was clicked

I am an Ember newbie and can't get my head around how to run events on specific elements populated via records on my ember model.
Here is my Template
{{#each user in model }}
{{#each activecredit in user.activecredits}}
<div class="col-lg-2 hive-credit-box active-credit">
<div class="credit-brandname">
{{activecredit.Brandname}}
</div>
<div class="credit-brand-image-container">
<img src="http://localhost:3000/{{activecredit.Imglocation}}" class="credit-image"/>
</div>
<div class="hive-credit-percent"><img class="hive-filled-container" src="imgs/hivefilled9.png"/></div>
<div class="hive-credit-dollars">$xx.xx</div>
<div {{bind-attr class=activecredit.Brandname}} {{action 'enableTrade'}}><img src="imgs/trade_button.png" class="credit-trade-button" /></div>
<div class="credit-brand-amount">
xx%
</div>
<!-- Trade button click dropdown -->
{{#if isSelected}}
<div class="hivetrade">
<div class="arrow_box">
Hi there
</div>
<div class=""></div>
</div>
{{/if}}
</div>
{{/each}}
{{/each}}
Now I want to show a drop down on each element on click of a button .
When I set the enableTrade action , all dropdowns of all the divs show up.
actions:{
enableTrade:function(){
this.set('isSelected',true);
}
}
How do I enable only the dropdown in the particular div that was created.
I suppose I need to bind certain attributes to each div,but how do I access which div was clicked in my controller?
Any help would be appreciated .
Thanks
You can pass params through the action helper, and use them to set isSelected on the appropriate item.
{{#each model as |user| }}
{{#each user.activeCredits as |activeCredit|}}
<button {{action 'enableTrade' activeCredit}}>Enable Trade</button>
{{#if activeCredit.isSelected}}
<div class="hivetrade">Hello World</div>
{{/if}}
{{/each}}
{{/each}}
To handle it:
actions:{
enableTrade:function(credit) {
credit.set('isSelected',true);
}
}
If you need to allow only one credit to be selected at a time, your controller and action could be modified like this:
selectedCredit: null,
actions:{
enableTrade:function(credit) {
// unselect the previously selected credit
if (this.get('selectedCredit')) {
this.set('selectedCredit.isSelected', false);
}
// select, and cache the selection choice
credit.set('isSelected',true);
this.set('selectedCredit', credit);
}
}

Knockout Template in foreach access specific template item

I am populating a list of survey questions. On click of a survey question, a modal with graphs of the results pop up. To create my list I am using a knockout template as I need the afterRender function.
Here's my markup:
<div id="priorityMenuW" class="priorityMenuW shadow">
<div class="menuHeader">Select a Survey Question:</div>
<div id="priorityMenu" data-bind="foreach:questionTypes">
<div class="menucategory menuItem" data-toggle="tooltip" data-bind="text:CategoryName, attr:{title:CategoryName}"></div>
<div class="menuitem" data-toggle="tooltip" data-bind="foreach:$root.questions">
<!-- ko if: CategoryName == $parent.CategoryName-->
<div data-bind='template: { name: "question-template",
data:$root.questions,
afterRender: $root.storeQuestionIdOrder }'>
</div>
<!-- /ko -->
</div>
</div>
</div>
And my template:
<code><script type="text/html" id="question-template">
<div class="menuItem" data-toggle="tooltip" data-bind="html:'• '+ $parent.QuestionText, attr:{title:$parent.QuestionText}, css: {'itemSelected' : $root.isPriorityActive($data)}, click: function($data,event){$root.questionChoice($data,event)}"></div></script></code>
My problem is that by sending $data to the function questionChoice, I am receiving an array of all of the templated objects. How can I access the specific object clicked on? I was thinking maybe $data[$index], but that doesn't work.
if you want to use $data[$index], remember that $index is an observable and needs to be evaluated:
$data[$index()]

Categories