Hide/show Button in LWC - salesforce

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

Related

Implementing dynamic dropdown menu in Polymer2.0. Works in Polymer1.0 but not in Polymer2.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.

ngx-popover cannot read 'show' of undefined

I am using ngx-popover, when try to open it from another component it was showing the following error
Cannot read property 'show' of undefined
below is the following code. home.html is the parent component
In
home.html
<button (click)="onShowPopOver()">Device</span>
<device-popover *ngIf="showPopover"></device-popover>
home.component.ts
onShowPopOver() {
this.showPopover=true;
}
and my devicePopover component looks follows
#ViewChild('myPopover') popover: Popover;
constructor() {
this.popover.show();
}
and my devicePopover.html looks as follows:
<popover-content #myPopover class="myPopover"
title="Add/remove an Emulator"
placement="bottom"
[animation]="true"
[closeOnClickOutside]="true" >
<span>Hello</span>
</popover-content>
device-popover is my selector for devicePopover component. when i try to call the child component it was hitting the constructor but throwing the error as "show of undefined"
#ViewChild refer to a child View, and this view is not created yet when your component is instanciated. You need to rely on a lifecycle hook to be able to access this popover property:
According to the docs :
ngAfterViewInit() Respond after Angular initializes the component's
views and child views.
Called once after the first ngAfterContentChecked().
A component-only hook.
#ViewChild() will get populated just before ngAfterViewInit is called.
You also need to put a template reference on your element if you want to use a string as argument to #ViewChild():
#ViewChild("myPopover")
<div popover #myPopover=popover *ngIf="showPopover"></div>
otherwise you should use a class as argument :
#ViewChild(Popover) //the popover from ngx-popover, not yours
<div popover *ngIf="showPopover"></div>
So this should work :
#ViewChild("myPopover") popover: Popover;
ngAfterViewInit() {
this.popover.show();
}
<div popover #myPopover=popover *ngIf="showPopover"></div>

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>

Appending value using React.js

I made todo app using jquery and now using react making same app. I made general layout of the app using react but facing problem in appending element by clicking button. The code i made in jquery was.
function entervalue()
{
var text = $('#inputext').val();
$("#list").append('<li class="item"> <input type="checkbox" class="option-input checkbox"> ' + text + '<button class="destroy"></button><li>');
$("#inputext").val('');
}
Here the value of input field is stored in var text.
List is appended in having checkbox, 'text' and a button.
I want same code to be written in react, so that when i click on button the following list gets appended.
Use state to store the new value. Save it as an array. React does a re-render when the state changes. During that render, map() through the value in the state and generate the HTML out of it.
this.setState({ //put this inside the 'onChange' handler of <input/>
value: e.target.value
})
This will set the new value to the state.
var todo = this.state.value.map(function(value){
return <li class="item"> <input type="checkbox" class="option-input checkbox">{value}<button class="destroy"></button><li>
})
todo will have the latest list of user inputs.
[UPDATE]
Check the example https://jsfiddle.net/Pranesh456/1veb7bdg/1/
jQuery is fundamentally different than React... you need to think of how you store data in state.. not actual DOM elements (jQuery like). You'll want to define your DOM elements in your render method and have it iterate through your state to generate the elements.
I made this repo to help teach a developer the transition from jQuery to React.. it might be helpful to checkout: https://github.com/bradbumbalough/react-tunes.
I also highly reccomend this doc if you're new to React: Thinking in React.

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