How to use Sessions and Templates to show/hide elements? - javascript

I have 7 question I want to ask individually one per time on the page. I have every of them in single template and I know I should use Session.set - Session.get to show/hide them one each time. But I really don't know how and can't find an good example of how to do it. This is how I structured layout template with 7 questions inserted.
<template name="layout">
{{#if first}}
{{> submitProblem}}
{{/if}}
{{#if second}}
{{> submitWhy}}
{{/if}}
...
</template>
First needs to be displayed when the page opens, and then I tried to do this with Sessions, but have no idea...
Meteor.startup(function () {
Session.set("first", true);
});
Template.layout.events({
'click .btn1':function() {
Session.set("first", false);
Session.set("second", true);
}
});
It seems to me that using jQuery to do show/hide with setting display:block/none is easier to do ?

If you want to hide items on page, you should define and use .hide or .hidden class in CSS. Showing/hiding items using jQuery show/hide is considered bad practice. You should render all hidden templates wrapped with .hidden class. The first template you want to show will not have hidden class.
CSS:
.hidden {
display: none;
}
Templates:
<template name="layout">
{{> submitProblem}}
{{> submitWhy}}
...
</template>
<template name="submitProblem">
<div id="submit-problem">
...
</div>
</template>
<template name="submitWhy">
<div id="submit-why" class="hidden">
...
</div>
</template>
JS:
Template.layout.events({
'click .btn1':function() {
//show/hide items with removeClass()/addClass()
$('#submit-problem').addClass('hidden');
$('#submit-why').removeClass('hidden');
}
});

Use template helpers to interpret whether first, second, etc are true or false.
Template.layout.helpers({
first: function() {
return Session.get('first');
},
second: function() {
return Session.get('second');
}
});

Related

Vue mouseover not causing changes to the data

I am trying to attach a v-mouseover directive to a bootstrap Vue element b-list-group-item as shown below.
<b-row>
<b-col cols="3">
<b-list-group>
<b-list-group-item :active="register"
#click="switchRegister" button
#mouseover="isRegisterHover = true"
#mouseleave="isRegisterHover = false"
class="border-0 bg-transparent register"> Register </b-list-group-item>
</b-list-group>
</b-col>
<b-col cols="9">
<div id="action-screen-canvas-register v-if="isRegisterHover"> </div>
</b-col>
</b-row>
The variable isRegisterHover is tied to the boolean value in the data which determines whether or not the div will be shown.
export default {
name: 'Home',
components: {
Navi
},
data() {
return {
isRegisterHover: false,
// ...
}
},
// ...
}
Thing is that the action-canvas-register div remains hidden when I hover the item, Vue devtool also shows that the data remains unchanged when I mouseover them. How do I make the isRegisterHover value change when I mouse-over the item?
You could also do this with pure CSS if you wanted to. You could do something like:
<template>
<div id="target">Hover this</div>
<div>...</div> // This will be hidden when #target is hovered
</template>
<script>
...
</script>
<style>
#target:hover + div {
visibility: hidden; // Hides the element like v-show
or
display: none; // Hides the element like v-if
}
</style>
Your code should work. See this:
I would recommend using v-show instead of v-if. See this.
<script>
export default {
data() {
return {
isRegisterHover: false
}
}
}
</script>
<template>
<div #mouseover="isRegisterHover = true"
#mouseleave="isRegisterHover = false">Hover this</div>
<div v-show="isRegisterHover">This will show/hide (v-show)</div>
<div v-if="isRegisterHover">This will show/hide (v-if)</div>
</template>

Nested Iron Ajax

Ok. So my last post was too ambiguous. For my second post, let me try to approach the same problem in hopefully a little more straighforward manner. Below is the code. Here is a screenshot of the results I get. Regarding the second iron-ajax call, if I use curl in terminal with this () I get what I want (it's a link preview service, so title, img, desc etc). Trying to accomplish the same with iron-ajax post with required parameters defined per spec. I don't get any console errors (for the first time) and based on the [object.Object] result I get when I output the last-response variable in the body of second dom-repeat, appears to be returning a json object just like the first iron-ajax call (which does work, includes the link but not enough data about it, hence running link through second service that returns the data I want to display).
Result from running code locally
CODE:
<dom-module id="my-new-view">
<template>
<!-- Defines the element's style and local DOM -->
<style>
:host {
display: block;
padding: 16px;
}
</style>
<iron-ajax auto
url="https://api.rss2json.com/v1/api.json?rss_url=http://feeds.feedburner.com/DrudgeReportFeed"
params="{"fmt":"xml-rss"}"
handle-as="json"
last-response="{{ajaxResponse}}"></iron-ajax>
<p>First: {{ajaxResponse}}</p>
<template is="dom-repeat" items="[[ajaxResponse.items]]" as="item" index-as="item_no">
<p>{{item.title}}</p>
<iron-ajax auto
method="post"
url="https://guteurls.de/api/"
params="{"u":"{{item.guid}}", "r":"https://127.0.0.1", "e":"s652imb8et42xd0bd", "t":"json"}"
handle-as="json"
last-response="{{newAjaxResponse}}"></iron-ajax>
<p>Second: {{newAjaxResponse}}</p>
<template is="dom-repeat" items="[[newAjaxResponse.newItems]]" as="newItem" index-as="newItem_no">
<p>{{newItem.title}}</p>
<paper-card heading="{{newItem.title}}" image="{{newItem.image.url}}" alt="{{newItem.title}}">
<div class="card-content">
<h1>Description: {{newItem.desc}}</h1>
<p>Test</p>
</div>
<div class="card-actions">{{newItem.title}}
<paper-button>Share</paper-button>
<paper-button>Explore!</paper-button>
</div>
</paper-card>
</template>
</template>
</template>
<script>
class MyNewView extends Polymer.Element {
static get is() { return 'my-new-view'; }
}
customElements.define(MyNewView.is, MyNewView);
</script>
</dom-module>
Problems and Solutions:
params="{"fmt":"xml-rss"}"
Quoting not done properly. You can you single quote as well like
params='{"fmt":"xml-rss"}' or params="{'fmt':'xml-rss'}"
First: {{ajaxResponse}} and Second: {{newAjaxResponse}}
You can use console to debug since you cannot display object like that
params="{"u":"{{item.guid}}", "r":"https://127.0.0.1", "e":"s652imb8et42xd0bd", "t":"json"}"
Quoting not done properly.
Attribute binding i.e. {{item.guid}} must be followed by $.
Change to params$='{"u":"{{item.guid}}", "r":"https://127.0.0.1", "e":"s652imb8et42xd0bd", "t":"json"}'
newAjaxResponse.newItems
There is no newItems in newAjaxResponse. Just use newAjaxResponse
[Note: newAjaxResponse is returned as Object which must be converted to Array since dom-repeat works only with Array.]
Before you define fields like desc, image.url make sure it exists.
Working code:
<dom-module id="my-new-view">
<template>
<!-- Defines the element's style and local DOM -->
<style>
:host {
display: block;
padding: 16px;
}
</style>
<iron-ajax auto url="https://api.rss2json.com/v1/api.json?rss_url=http://feeds.feedburner.com/DrudgeReportFeed" params='{"fmt":"xml-rss"}' handle-as="json" last-response="{{ajaxResponse}}"></iron-ajax>
<p>First: {{ajaxResponse}}</p>
<template is="dom-repeat" items="[[ajaxResponse.items]]" as="item" index-as="item_no">
<p>{{item.title}}</p>
<iron-ajax auto method="post" url="https://guteurls.de/api/" params$='{"u":"{{item.guid}}", "r":"https://127.0.0.1", "e":"s652imb8et42xd0bd", "t":"json"}' handle-as="json" last-response="{{newAjaxResponse}}"></iron-ajax>
<p>Second: {{newAjaxResponse}}</p>
<template is="dom-repeat" items="[[_toArray(newAjaxResponse)]]" as="newItem" index-as="newItem_no">
<paper-card heading="{{newItem.title}}" image="{{newItem.img}}" alt="{{newItem.title}}">
<div class="card-content">
<h1>Description: {{newItem.description}}</h1>
<p>Test</p>
</div>
<div class="card-actions">{{newItem.title}}
<paper-button>Share</paper-button>
<paper-button>Explore!</paper-button>
</div>
</paper-card>
</template>
</template>
</template>
<script>
class MyNewView extends Polymer.Element {
static get is() { return 'my-new-view'; }
_toArray(obj) {
var tempArray = [];
tempArray.push(obj);
//console.log(tempArray);
return tempArray;
}
}
customElements.define(MyNewView.is, MyNewView);
</script>
</dom-module>
You can check the working demo here.

Polymer iron-list not updating view on dynamic add

I am using Polymer 1.7.0 and Angular2 to build a app. I created a custom Polymer element to wrap the iron-list template in order to be able to use it with Angular2 but i have a problem when it comes to dynamicly adding items to the iron-list.
The add function modifies the items array but it doesnt render the new element even if i am triggering the iron-resize event after modifying the items array.
If i delete a item first, and then try to add a element, then it gets rendered.
This is the polymer element i use:
<!--.... dependencies imports .... -->
<dom-module id="role-users-list">
<template>
<style is="custom-style" include="iron-flex iron-flex-alignment custom-layout-classes">
:host {
display: block;
}
</style>
<iron-media-query query="(min-width: 600px)" on-query-matches-changed="queryValueChanged" query-matches="{{wide}}"></iron-media-query>
<iron-list items="{{items}}" class="test" style="height:85%">
<template>
<paper-card class="verticalJustified">
<div class="horizontalJustified">
<div class="card-content horizontalJustified">
<paper-icon-button class="cardIcons" icon="group-work"></paper-icon-button>
<div class="verticalStart">
<span class="cardTitle">{{item.fullName}}</span>
<template is="dom-if" if="{{item.direct}}">
<span class="cardSubTitle">User associated directly </span>
</template>
<template is="dom-if" if="{{!item.direct}}">
<span class="cardSubTitle">Role granted through {{item.groupName}} </span>
</template>
</div>
</div>
<template is="dom-if" if="{{item.direct}}">
<div class="horizontalJustified">
<paper-icon-button class="cardIcons" icon="delete" target-user="{{item.username}}" on-tap="onDelete" (click)="deleteUser(user)"></paper-icon-button>
</div>
</template>
</div>
</paper-card>
</template>
</iron-list>
</template>
<script>
Polymer({
is: 'role-users-list',
onDelete: function(e){
this.fire("deleteTrigger",{data:e.model.item});
},
queryValueChanged: function(e){
this.fire("mediaQueryTrigger",{data: e.detail.value})
},
updateIronList:function(){
this._nodes.filter(function(value){return value.localName === "iron-list"})[0].fire("iron-resize");
},
focusElem:function(){
var test = this._nodes.filter(function(value){return value.localName === "iron-list"})[0];
test.selectItem(this.items[0]);
},
properties: {
items: {
type: Array,
notify: true,
value:[],
}
}
});
</script>
</dom-module>
After adding or removing a element i call the updateIronList function to trigger the rendering with the iron-resize event.
PS: The add functionality is in the parent Angular2 component where i modify the items array.
The only difference i could notice was that since the delete button is inside the polymer custom element, it causes it to focus that item when its clicked.
If i didnt make myself understood, ask and i will clarify.
I fixed my issue by updating the updateIronList function to:
updateIronList:function(){
let ironListElem = this._nodes.filter(function(value){return value.localName === "iron-list"})[0];
ironListElem.fire("iron-resize");
ironListElem._virtualCount = (this.items.length <= 20) ? this.items.length : 20;
},
It seems the issue was caused by the fact that when the items array length changed, iron-list didnt automaticly update the number of items displayed.

Add events for elements from a container [duplicate]

Here, I would like to select the .accept element from within the .header element. Is this possible? The documentation is inconclusive and I have tried some variations to no avail, is there a trick I'm not aware of?
'click .header .accept': function (event) { ... },
In jQuery I might use this: $('.header .accept')
What you shared will work assuming you don't have a conflict elsewhere. Try using the code below. The event fires only if you click the second div, as you want.
template:
<body>
{{> page}}
</body>
<template name="page">
<div class="header">.header
<div class="accept">.header .accept</div>
</div>
</template>
js:
if (Meteor.isClient) {
Template.page.events({
'click .header .accept': function(event) {
console.log('accept clicked');
}
});
}

Is it possible to use nested selectors in Meteor event maps?

Here, I would like to select the .accept element from within the .header element. Is this possible? The documentation is inconclusive and I have tried some variations to no avail, is there a trick I'm not aware of?
'click .header .accept': function (event) { ... },
In jQuery I might use this: $('.header .accept')
What you shared will work assuming you don't have a conflict elsewhere. Try using the code below. The event fires only if you click the second div, as you want.
template:
<body>
{{> page}}
</body>
<template name="page">
<div class="header">.header
<div class="accept">.header .accept</div>
</div>
</template>
js:
if (Meteor.isClient) {
Template.page.events({
'click .header .accept': function(event) {
console.log('accept clicked');
}
});
}

Categories

Resources