Implementing dynamic dropdown menu in Polymer2.0. Works in Polymer1.0 but not in Polymer2.0 - polymer-1.0

I've done the following using Polymer1. Doing the same in Polymer2.0 does not trigger the automatic dropdown menu of the button.
Please could someone tell me what to do. It seems to have to do with Shadow DOM.
In Polymer1, the index.html has dom ='shadow', and a <content> tag instead of <slot>, and it gets to the dReadyDynamicRightMenuReady and triggers the dropdown.
But in Polymer2.0 it also gets to this function, and does not trigger the dropdown.
<!-- this is in my-spxl Polymer2.0 -->
<paper-menu-button class="userMenuPositionClass">
<paper-icon-button icon="menu" class="dropdown-trigger"></paper-icon-button>
<paper-dropdown-menu class="dropdown-content">
<iron-selector selected="[[choice]]" attr-for-selected="mychoice" role="navigation">
<template id="" is="dom-repeat" items="[[dReadyDynamicRightMenuReady]]" as="menuOption">
<paper-item>... </paper-item>
</template>
</iron-selector>
</paper-dropdown-menu>
</paper-menu-button>
<paper-button class="">
<img on-tap="openRightMenuFromPhoto" src="[[user.photoURL]]">
</paper-button>
Script:
openRightMenuFromPhoto() {
var usersMenuButton = this.$.userMenuIconId;
usersMenuButton.click(function(event) {
dReadyDynamicRightMenuReady = [
{ "myChoice": "spx21", "myHref": "/spx21", "myOptionValue": "chats" }
];
return dReadyDynamicRightMenuReady;
})
}

There are few mistakes in your code:
Handle and firing events:
Click listeners is inside a function. That will never be called. Put event listeners on ready() or connectedCallback. For more information about how to do that click here.
Setting property value:
Setting properties value inside function and returning it won't set it. Use
this.property = value and notify the changes. OR, if it is an array/object use polymer array mutation methods.
Read the documentation of paper-menu-button:
Instead of class='dropdown-trigger' use slot as in documentation.
Also, try to create a Minimal, Complete, and Verifiable example.

Related

Cypress: Element not found inside cypress

Content is inside the iframe:
it.only('should verify xyz tooltips',()=>{
cy.visit('/');
cy.get('a[ng-reflect-router-link="abc"]').click();
cy.wait(9000)
cy.get('iframe')
.then( ($iframe) => {
const $body = $iframe.contents().find('body')
cy.wrap($body).find('.content').invoke('attr','style', 'overflow: visible')
//upto here it is working fine
cy.wrap($body).find('div.visTooltip').invoke('attr','style', 'visibility:
visible').invoke('attr','style', 'overflow: visible')
//Below statement is not working
cy.wrap($body).find('div.visTooltip > table.visTooltip__table').should('have.length',1)
})
});
HTML of the page that is not working
I'm successfully able to locate upto div tag using cy.wrap($body).find('div.visTooltip') but after that code is not finding table inside div tag.
I tried setting up css property visibility and overflow to visible but nothing is working.
Can somebody please have a look and suggest something?
Have you tried cypress example on how to use find?
https://docs.cypress.io/api/commands/find.html#Syntax
Example from link above
Get li’s within parent
<ul id="parent">
<li class="first"></li>
<li class="second"></li>
</ul>
// yields [<li class="first"></li>, <li class="second"></li>]
cy.get('#parent').find('li')

Hide/show Button in LWC

I'm new to LWC in salesforce and want to hide/show the button based status. I write below code but it is hiding for all statuses. Can you please help me if am wrong.
<template for:each={savedCampaignList} for:item="savedCampaignListvar">
<a name={savedCampaignListvar.Id} >View</a>
|
<a hidden =!IF(savedCampaignListvar.Status === 'Saved')" name={savedCampaignListvar.Id} >Delete</a>
</template>
Expressions are different in LWC than in aura and visualforce
You need to have a getter defined in your controller the template uses for expressions or have a tracked variable you update.
See this for migrating to lwc
You'll end up making a getter like this
get hideLink() {
return this.savedCampaignListvar.Status === 'Saved';
}
and then in your lwc markup you should have this
<template if:false={hideLink}>
<a name={savedCampaignListvar.Id}>Delete</a>
</template>
Note: the hidden attribute is not a boolean attribute. If the attribute exists regardless of setting it to true/false hides the element. See here
Use this code in your HTML template - remember don't put any attribute in your root 'template' element use another div as a holder for for:each directive. You must use a key directive to assign a unique ID to each item. When a list changes, the framework uses the key to rerender only the item that changed. The key in the template is used for performance optimization and isn’t reflected in the DOM at run time.
<template>
<div for:each={savedCampaignList} for:item="savedCampaignListvar" key={savedCampaignListvar.Id}>
<a name={savedCampaignListvar.Id} >View</a>
|
<a if:true={savedCampaignListvar.shouldShow} name={savedCampaignListvar.Id} >Delete</a>
</div>
</template>
We can use connectedCallback function - it's build in LWC function called when the element is inserted into a document. There we can put some condition and add 'shouldShow'(you can call if whatever you want of course;)) attribute to our Objects inside the array. Based on this attribute we will show delete button or not. Your JS should looks like:
import { LightningElement, track } from 'lwc';
export default class App extends LightningElement {
#track savedCampaignList = [
{Id: "1", status: 'Saved'},
{Id: "2", status: 'Not Saved'}
]
connectedCallback() {
this.savedCampaignList.forEach((el)=> {
el.shouldShow = el.status === 'Saved';
})
}
}
You can use if:true or if:hide.
Go through this https://salesforcelightningweb.com/#conditionally-render-html-in-lightning-web-component

knockout binding is not working for enable button after ko.applyBindings in bootstrap modal

I'm trying to enable a button after check a checkbox, the elements are in a modal. I'm using MVC, and I'm adding the observables after the main binding for use them just with the modal like this
<script type="text/javascript">
var Model = function () {
self.check = ko.observable(false);
};
$(document).ready(function () {
ko.cleanNode($('#Modal')[0]);
ko.applyBindings(Model, $('#Modal')[0]);
});
</script>
The html elements inside the modal look like this:
<input type="checkbox" data-bind="checked:viewModel.check">bla bla..
<button type="button" data-bind="enable:viewModel.check==true" class="btn btn-primary">Delete</button>
when I select the checkbox the viewModel.check is true and when is not checked is false which is working fine but the button is always disable. Any advise please
Several issues...
Un-instantiated ViewModel
When calling ko.applyBindings, the first argument needs to be a viewModel instance. This means you need to call new on your viewModel "class."
ko.applyBindings(new Model())
Incorrect scope in HTML
You are referencing a viewModel variable which does not exist. When you apply bindings, it uses the scope of the viewModel passed to in to create the binding context. This means that the values available to you in the HTML are the same as those on this in your viewModel. So, just use check.
enable binding bound to expression, not observable
The enable binding must be bound to an observable, but you have bound it to the expression check==true. In this case, check is actually an observable — this.check = ko.observable(), so what you're ultimately comparing is something to the effect of function() { return true } == true, which is expectedly false. To do comparisons on observables, you must first unwrap them by calling them as a function: check() == true. Note, however, that anytime you're writing == true, you probably don't need to: enable: check is what you ultimately want.
and a fiddle

reference component variable from ng-content

I have the following piece of markup:
<group-header [isOpen]="true">
<div *ngIf="isOpen">{{'PRICE' | resource}}</div>
</group-header>
group-header's template looks like this:
<div (click)="toggleGroups($event);">
<ng-content></ng-content>
</div>
isOpen is defined in my group-header component like this:
#Input()
set isOpen(value: boolean) {
this._isOpen = value;
}
get isOpen() {
return this._isOpen;
}
Apparently I cannot reference isOpen the way I want to (or at all for that matter) as my 'PRICE' resource never displays.
Is there a way to have my ng-content rendered content display conditionally based on a field on my component?
Hope this all makes sense... if not please ask
EDIT: Added setter as per #PierreDuc's comment :-)
You can use a template variable to reference the GroupHeader component:
<group-header [isOpen]="true" #gh>
<div *ngIf="gh.isOpen">{{'PRICE' | resource}}</div>
</group-header>

ng-class conditional value not getting reflected

I have a list. I want to show the selected object as active. For that I have written the code as below:
HTML
<li ng-class="{'active' : testObject.selected}" >
<a ng-click="showApp()">
<span>App</span>
</a>
</li>
Controller
$scope.testObject = {
selected: false
};
$scope.showApp = function() {
$scope.testObject['selected'] = true;
//my code
}
Here, testObject.selected is a boolean and I am setting its value (true/false) inside showApp() function. It is not working somehow.
There are no issues with your code... I copied it into here a plnkr here:
http://plnkr.co/edit/pjNBHvCnju4zs7QTZ87C?p=preview
Are you sure the class of active has CSS in it that will be reflected in your view?
Have you verified that the class is actually being added to the element or not via the browser dev tools?
If you work with a form, then make sure you have checked your <form> element.
Each required <input> should have binding with a variable via [(ng-model)] (two-way binding is necessary in this case).
I had the same issue and ng-class worked correctly only after these changes.

Resources