Perform actions on component initialization in LWC - initialization

I recently started learning LWC. I am working on a requirement in LWC where on component initialization I need to use record Id to get value of numeric field from same object/record, check if it is 100 and display a message on component html. Note - this LWC is used as a quick action of type Screen Action. Following is current implementation which works at times and doesn't (not sure if it is a cache issue).
LWCComponent.html
<template>
<!-- modal start -->
<template if:true={isShowModal}>
<lightning-quick-action-panel header="New Record">
<div class="slds-modal__content modalBodySpinner" style="width: 100%;" id="modal-content-id-1">
<template if:true={isLoaded}>
<lightning-spinner alternative-text="Loading" size="medium" class="spinnerClass"></lightning-spinner>
</template>
<div slot>
<lightning-layout>
<lightning-layout-item size="6" padding="around-small">
<lightning-input label="Record Name" type = "text" value={recordName}></lightning-input>
</lightning-layout-item>
</lightning-layout>
</div>
<template if:true={recordId}></template>
<template if:true={showForm}>
<lightning-input label="Record ID" type="text"></lightning-input>
</template>
<template if:false={showForm}>
<p class="warningP">{restrictMessage}</p>
</template>
<br/>
</div>
<div slot="footer">
<lightning-button variant="neutral" label="Cancel" onclick={closeModal}></lightning-button>
</div>
</lightning-quick-action-panel>
</template>
<!-- modal end -->
</template>
LWCComponent.js
import { LightningElement, track, api, wire } from 'lwc';
import { getRecord, getFieldValue } from "lightning/uiRecordApi";
import NAME from "#salesforce/schema/CustomObject__c.Name";
import CAPACITY from "#salesforce/schema/CustomObject__c.Capacity__c";
import { CloseActionScreenEvent } from 'lightning/actions';
import restrictMessage from "#salesforce/label/c.RestrictWarning";
const fields = [NAME, CAPACITY];
export default class NewClass extends LightningElement {
#track isShowModal = true;
#track showForm = true;
#api recordId;
#track isLoaded = true;
#api capacityVal;
#track warningMsg;
#track retrievedRecordId = false;
#wire(getRecord, {
recordId: "$recordId",
fields
})
custObjRec;
get recordName() {
return getFieldValue(this.custObjRec.data, NAME);
}
renderedCallback() {
if(!this.retrievedRecordId && this.recordId) {
this.retrievedRecordId = true;
this.capacityVal = getFieldValue(this.custObjRec.data, CAPACITY)
if(this.capacityVal == 100) {
this.showForm = false;
this.warningMsg = restrictMessage;
this.isLoaded = false;
}
else {
this.isLoaded = false;
}
}
else {
this.isLoaded = false;
}
}
// method to close modal pop up
closeModal() {
this.dispatchEvent(new CloseActionScreenEvent());
}
}
Any suggestions to make this better?

Related

reCAPTCHA not loading properly in XHTML document

I am writing an SHTML CSS & JS document into an XML document which uses an XHTML parser.
When I try to load the captcha into it, it briefly shows up as a white box then disappears, never to be seen again inside the renderer.
I understand that this might be caused by the scripts being loaded in the wrong order but I don't have the luxury of the async defer keywords that are recommended by google simply because the parser won't accept them.
<script src="https://www.google.com/recaptcha/api.js" type="text/javascript"></script>
<script type="text/javascript"><![CDATA[
class Token {
constructor(tokenInstance) {
this.props = tokenInstance;
this.getStatus();
this.setOnConfirm();
this.setAdditionalProps();
}
setAdditionalProps() {
this.props.claimed = false;
this.props.claimTokensMessage = "Claim free DAI, DeFi & ETH tokens";
this.props.claimedMessage = "You have already claimed DAI, DeFi & ETH tokens, stay posted for new freebies!";
this.props.serverError = "Server Error, please try again later";
this.props.success = "ETH, DeFi & DAI tokens will be sent to your address shortly!";
this.props.fillCaptchaMessage = "Please click the captcha below to receive the tokens";
}
getBaseURL() {
return "http://192.168.26.189:8080/api/"
}
getStatus() {
let suffix = "claimed?userAddress=" + this.props.ownerAddress;
fetch(this.getBaseURL() + suffix).then((res) => {
if(parseInt(res.status) === 200) {
document.getElementById("message").innerHTML = this.props.claimTokensMessage;
} else if(parseInt(res.status) === 412) {
this.props.claimed = true;
document.getElementById("message").innerHTML = this.props.claimedMessage;
} else {
document.getElementById("message").innerHTML = this.props.serverError;
}
}).catch((err) => {
document.getElementById("message").innerHTML = err;
window.onConfirm = function() { window.close() };
});
}
setOnConfirm() {
window.onConfirm = () => {
if(this.props.claimed) {
window.close();
} else {
web3.personal.sign({ data: "To receive free tokens, you must reveal your public address to a smart contract. Is that ok?" }, (err, val) => {
if(err) { throw err; }
//user completes the request by filling the captcha
document.getElementById("message").innerHTML = this.props.success;
document.getElementById("captcha").submit();
window.onConfirm = function () { window.close(); };
});
}
};
}
render() {
let suffix = "discover?userAddress=" + this.props.ownerAddress;
return`
<div class="ui container">
<div class="ui segment">
<img src="data:image/png;base64,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">
<h3 id="message"></h3>
<form action=${this.getBaseURL() + suffix} id="captcha" method="post">
<button class="g-recaptcha" data-sitekey="6LeK070UAAAAAHuzSEGgoqbuLGuJq-GRDd-LA4kH" data-callback="onSubmit" hidden>fill captcha</button>
</form>
</div>
</div>
`;
}
}
web3.tokens.dataChanged = (oldTokens, updatedTokens) => {
const currentTokenInstance = web3.tokens.data.currentInstance;
document.getElementById('root').innerHTML = new Token(currentTokenInstance).render();
};
]]></script>
<div id="root"></div>

Firebase: Why value event gets fired before new child ref gets added

Following code, is a very simple Firebase - VueJS app, (codeSandBox demo)
app.vue
<template>
<div class="container">
<!-- Adding Quote -->
<add-quote/>
<!-- Display Quotes -->
<quote-list/>
</div>
</template>
<script>
import addQuote from "./components/AddQuote.vue";
import quoteList from "./components/QuoteList.vue";
export default {
components: {
addQuote,
quoteList
},
methods: {
get_allQuotes: function() {
// var vm = this;
var localArr = [];
quotesRef
.once("value", function(snapshot) {
snapshot.forEach(function(snap) {
localArr.push({
key: snap.key,
category: snap.val().category,
quoteTxt: snap.val().quoteTxt
});
});
})
.then(data => {
this.$store.commit("set_allQuotes", localArr);
});
}
},
mounted() {
this.get_allQuotes();
console.log("App: mounted fired");
}
};
</script>
store.js(vuex store)
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
quotesList: []
},
getters: {
get_quotesList(state) {
return state.quotesList;
}
},
mutations: {
set_allQuotes(state, value) {
state.quotesList = value;
}
}
});
AddQuote.vue
<template>
<div class="row quote-edit-wrapper">
<div class="col-xs-6">
<textarea v-model.lazy="newQuoteTxt"
rows="4"
cols="50"></textarea>
<button #click="addQuote">Add Quote</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
newQuoteTxt: '',
}
},
computed: {
allQuotes() {
return this.$store.getters.get_quotesList;
},
newQuoteIdx() {
var localArr = [...this.allQuotes]
if(localArr.length > 0) {
var highestKEY, currKEY
localArr.forEach((element, idx) => {
currKEY = parseInt(element.key)
if(idx == 0) {
highestKEY = currKEY
} else {
if(highestKEY < currKEY) {
highestKEY = currKEY
}
}
})
return highestKEY + 1
} else {
return 1
}
}
},
methods: {
// ADD new Quote in DB
addQuote: function() {
var vm = this
var localArr = [...this.allQuotes]
//1. First attach 'value' event listener,
// Snapshot will contain data from that ref
// when any child node is added/updated/delete
quotesRef.on('value', function (snapshot) {
snapshot.forEach(function(snap) {
var itemExists = localArr.some(function (item, idx) {
return item.key == snap.key
})
// If newly added item doesn't yet exists then add to local array
if (!(itemExists)) {
localArr.push({
key: snap.key,
category: snap.val().category,
quoteTxt: snap.val().quoteTxt })
vm.$store.commit('set_allQuotes', localArr)
}
})
})
//2. Second set/create a new quotes in Firebase,
// When this quote gets added in Firebase,
// value event (attached earlier) gets fired
// with
var newQuoteRef = quotesRef.child(this.newQuoteIdx)
newQuoteRef.set({
category: 'motivation',
quoteTxt: this.newQuoteTxt
})
}
}
}
</script>
quoteList.vue
<template>
<div class="row">
<div class="col-xs-12 quotes-list-wrapper">
<template v-for="(quote,idx) in allQuotes">
<!-- Quote block -->
<div class="quote-block-item">
<p class="quote-txt"> {{quote.quoteTxt}} </p>
</div>
</template>
</div>
</div>
</template>
<script>
export default {
computed: {
allQuotes() {
return this.$store.getters.get_quotesList;
}
}
}
</script>
Note: The main code of concern is of addQuote.vue
User enter newQuoteTxt that gets added to Firebase (addQuote()) as a quote item under quotesRef. As soon as quote is added (on firebase), Firebase client side SDK's value event fires, and adds the new quote (via callback) to localArray (allQuotes). VueJS then updates the DOM with newly added Quote.
The addQuote() method works in the following manner:
First, attach a callback/listener to 'value' event on quotesRef
quotesRef.on('value', function (snapshot) {
....
})
Next, A firebase ref (child of quotesRef) is created with a ID this.newQuoteIdx
var newQuoteRef = quotesRef.child(this.newQuoteIdx)
Then set() is called (on this newly created Ref) adding newquote to firebase RealTime DB.
value event gets triggered (attached from step 1) and listener /callback is called.
The callback looks for this new quote's key in existing list of items by matching keys of localArr and snap.key, if not found, adds the newly quote to localArr. localArr commits to a vuex store.
`vm.$store.commit('set_allQuotes', localArr)`
VueX then updates all subscriber component of this array. VueJS then adds the new quote to the existing list of quotes (updates the DOM)
While debugging the addQuote method, the problem I notice, the execution/flow of script (via F8 in chrome debugger) first steps into the listener/callback attached to value event before the code newQuoteRef.set({ ... }) that adds new quote (on firebase), which in turn will cause 'value' event to trigger.
I am not sure why this occurs. Can anybuddy explain why the listener/callback is called before the quotes is created.
Are child nodes (of QuotesRef) are cached at clientside such that 'value' fires even before new quote is added.
Thanks
If I correctly understand your question (Your code is not extremely easy to follow! :-)) it is the normal behaviour. As explained in the documentation:
The value event will trigger once with the initial data stored at
this location, and then trigger again each time the data
changes.
Your sandbox demo does not actually shows how the app works, but normally you should not set-up the listener in the method that saves a new node to the database. These two things should be decoupled.
One common approach is to set the listener in the created hook of a component (see https://v2.vuejs.org/v2/guide/instance.html#Instance-Lifecycle-Hooks and https://v2.vuejs.org/v2/api/#created) and then in your addQuote method you just write to the database. As soon as you write, the listener will be fired.

Picking an item from Firebase on button click

I'm working with Angular 6 and Firebase and what I need is to get all items from the firebase and then display only one at a time till next button click
/*this is the .ts file*/
constructor( public af: AngularFire, public db: AngularFireDatabase) {
this.items = db.list('items').valueChanges();
db.list('/sentences').valueChanges().subscribe(sentences => {
this.sentences = sentences;
console.log(this.sentences);
});
}
<!--this in the html-->
<div>
<ul class="sent">
<li *ngFor="let sentence of sentences"
[class.selected]="sentence === selectedsentence"
(click)="onSelect(sentence)">{{sentence}}
<!-- this is displaying all the items in the firebase; i need only one at a time-->
</li>
</ul>
</div>
//in the ts file
constructor( public db: AngularFireDatabase) {
this.items = db.list('items').valueChanges();
db.list('/sentences').valueChanges().subscribe(sentences => {
this.sentences = sentences;
console.log(this.sentences);
this.labels = this.sentences; //in this.labels we have all the elements *declaration : labels=[]
console.log(this.labels);
});
onSkip($i) {
if (this.i > 13) { //if there are 13 elements in the database
this.i = 0;
}
this.i = this.i + 1;
console.log(this.i);
}
// in the html code
{{labels[i]}}
<button class="centered" (click)="onSkip(i)" > SKIP <a routerLink="skip">

Re-render templates on route change in Meteor 1.3

I'm using Flow Router and Blaze Renderer for a simple website (think blog / brochureware).
I'm using FlowRouter.path() to create links on my menu elements. The url changes as expected when these links are clicked and the action() method on the route is fired. However the templates don't seem to be refreshed and the template helpers aren't fired.
The route in my /lib/route.js file is
const about = FlowRouter.group({
prefix: '/about'
});
about.route('/:pageSlug/:subSectionSlug', {
action: (params) => {
console.log('action() fired :' + params.pageSlug + ' :' + params.subSectionSlug);
BlazeLayout.render( 'applicationLayout', {
main: 'basicPage',
});
},
name: 'pageSubsection',
});
Then my templates looks like -
<template name="applicationLayout">
{{> Template.dynamic template=main}}
</template>
<template name="basicPage">
<div id="pageWrapper">
...
<aside class="leftBar subSectionMenu">
{{> sidebar }}
</aside>
...
</div>
</template>
<template name="sidebar">
<ul class="pageMenu">
{{#each subSections }}
{{> sidebarItem}}
{{/each}}
</ul>
</template>
<template name="sidebarItem">
<a class="sidebarItemAnchor" href="{{ href }}">
<li class="sidebarItem .hoverItem {{#if isSelected }} selected {{/if}}">
{{title}}
<span class="sidebarArrow"></span>
</li>
</a>
</template>
With a simple helper to add the selected class to the li element -
Template.sidebarItem.helpers({
href() {
const subSection = this;
const params = {
pageSlug: subSection.pageSlug,
subSectionSlug: subSection.slug,
}
return FlowRouter.path('pageSubsection', params, {});
},
isSelected() {
const slug = FlowRouter.current().params.subSectionSlug;
console.log('running isSelected with ' + slug);
if (this.slug === slug) {
return true;
} else {
return false;
}
}
});
I think I must be misunderstanding how (and when) templates are rendered.
What do I need to do to re-render these templates when the route changes?
Flow Router was designed to work like this. It doesn't automatically re-render.
A simple fix is to add FlowRouter.watchPathChange(); into all Template helpers that depend on the params of a route.
So in this case update the sidebar.js -
Template.sidebarItem.helpers({
isSelected() {
FlowRouter.watchPathChange();
const slug = FlowRouter.current().params.subSectionSlug;
if (this.slug === slug) {
return true;
} else {
return false;
}
},
});
When that helper is used in the sidebarItem template it is now updated whenever the path changes.

Passing data between angular controllers using service

I am having trouble passing data between controllers using a service. What i want to happen is when send data is clicked the data inputted into the text field should be populated in the Results controller. However nothing shows
Home.html:
<html>
<body>
<ion-header-bar class="bar-dark">
<h1 class="title"></h1>
</ion-header-bar>
<ion-view view-title="Home">
<ion-content ng-controller="StockUpdateCtrl">
<div class="list">
<ion-refresher pulling-text="Pull to Refresh" on-refresh="doRefresh()"></ion-refresher>
<div>{{text}}</div>
<input type='text' ng-model='text' />
<button type='button' ng-click='send()'>Send Data</button>
<div ng-controller='ResultsController'>
<div>
<h4>Ctrl2</h4>
<div>{{text}}</div>
</div>
</div>
</ion-content>
</ion-view>
</body>
</html>
HomeController.js:
var app = angular.module('starter', ['ionic'])
.run(function ($ionicPlatform) {
$ionicPlatform.ready(function () {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if (window.StatusBar) {
StatusBar.styleDefault();
}
});
})
/*
* Data Service
* Service used to pass data between controllers
*/
app.factory('dataShare', function(){
var service = {};
service.data = false;
service.sendData = function(data){
this.data = data;
$rootScope.$broadcast('data_shared');
};
service.getData = function(){
return this.data;
};
return service;
});
/*
* Stock Update Controller
* Gets user input and then performs calculations to prepare to be displayed
*
*/
app.controller("StockUpdateCtrl", function ($scope, $http, dataShare) {
$scope.text = 'Hey';
$scope.send = function(){
dataShare.sendData($scope.text);
};
});
ResultsController.js:
* Resultse Controller
* Displays the results
*
*/
app.controller("ResultsController",function ($scope, dataShare) {
$scope.text = '';
$scope.$on('data_shared',function(){
var text = dataShare.getData();
$scope.text = text;
});
});
Haha figured it out. Yes it turned out it was the way i was calling the results page... I had to remove form tag
<form action="index.html#/results" ng-controller="StockUpdateCtrl">
and change my button to call the results page as such
<button type="submit" ui-sref="results" ng-click="calculate()" class="button button-block button-balanced">

Resources