2

For some reason, I can't get this while-loop to work. The code in the export default class runs once, and I can never call back to it when variables are change from another LWC, and imported back to this file.

My code:

mapping.js

import { LightningElement, wire, api, track } from 'lwc';
import { MapMarkers } from './MapMarkers';
import { SearchString, SearchState, ClickCount } from 'c/mappingBox';

// Global Variables.
let SearchStreet = '1 abc street';
let SearchCity = 'Boston';

export default class Mapping extends LightningElement {

// Method should rerun updating when the button is clicked from the MappingBox.js file; (not working).
    SearchClick(event) {

        // The address entered into the search bar.
        const ArrStreet = SearchString.split(',');
        SearchStreet = ArrStreet[0];

        // The town or city entered into the search bar.
        const ArrCity = SearchString.split(',');
        SearchCity = ArrCity[1];

        // Updates and locates the location searched.
        this.mapMarkers = MapMarkers(SearchCity, SearchState, SearchStreet);

    }
        
    // What populates, before searching is done.
    mapMarkers = MapMarkers(SearchCity, SearchState, SearchStreet);

    // Not working?
    while( ClickCount = true ){

        this.SearchClick();
        ClickCount = false;

    }

}

mappingBox

 // Function when the search button is clicked.
    SearchClick(event) {

        SearchString = this.SearchText;
    
        ClickCount = true;

    }

More Detail:

"ClickCount" is then export to "mapping.js" file.

For some reason I can't get the method "SearchClick" from the "mapping.js" file to rerun, so the variable can update and output a different location on the mapping function.

3 Answers 3

2

You'll want to look at Communicate Across the DOM for details, but it appears that what you're looking for is a publisher-subscriber model. The documentation contains two examples, first using a generic pubsub library you can copy-paste into your project, the other using lightning-message-service. The general idea is the same for each; you subscribe to a message channel when the component loads, unsubscribe when a component unloads, and then you can publish when you want to fire off an event that subscribers will receive. You can still use your shared state variable, you'll just read the values when you get a message.

export default class MappingBox extends LightningComponent {
  connectedCallback() {
    subscribe('searchUpdated', this.#subscription);
  }
  disconnectedCallback() {
    unsubscribe('searchUpdated', this.#subscription);
  }
  // Note use of arrow function to bind to the class scope
  #subscription = (message) => {
    // Do something 
  }
3
  • I been researching the "publisher-subscriber model", and just to double-check. I can run the method in mappingBox, when the method is clicked in mapping? Commented Apr 7, 2023 at 16:59
  • @Pinto Correct. You will register a method to accept the published message with the subscribe function, and that method will be called when the publish function is called. Commented Apr 7, 2023 at 17:41
  • Update: I was able to get it working! I looked into Lightning Message Service, and I had to create a "messageChannels" folder. Then used the subscribe and publish model, so I could rerun my method in a different LWC. Thank you! Commented Apr 7, 2023 at 19:36
2

This is not the right way to implement reactivity or component-to-component communication in a Lightning Web Component. You cannot use a synchronous while loop to poll for changes in a global variable (this would block the thread, although the way your loop is currently written it's only going to execute once anyway). You could use setTimeout() to create a poller, but that's not really the right approach either - you generally should not be sharing state through global variables like this.

Instead, you should rely on the LWC framework's built-in capabilities. Check out Reactivity and Composition for detailed documentation.

In outline, here's what I think you'd want to do here - although do note that there's more than one way to accomplish something like this outcome, and you haven't shared a lot of context here. I'm assuming that mappingBox contains input fields. You would declare data properties in mappingBox to store your user input, and populate those properties via event handlers. Then, you would declare the properties that you wish to pass from your mappingBox component to your Mapping component as API properties of Mapping, using the @api decorator, and bind them to the mappingBox properties. (See the link above for details).

It's not entirely clear to me where the event handler "should" go for executing a search. Possibly you'd want that to be in the mappingBox component and have it call a method on the child component.


Separately, you should also review Caspar's answer to understand why this code does not do what you think it'll do.

2
  • They're apparently in unrelated areas of the DOM. I do generally agree that direct communication is best, but they could, for example, be in App Builder or something and unable to nest components directly. They've actually had a lot of Q's in the past while trying to figure this out. Commented Apr 6, 2023 at 23:30
  • Ah, thanks, @sfdcfox. I missed that important context. Pinto - this is really important to share so that folks can help you get to the solution! Commented Apr 6, 2023 at 23:49
0

You are making an assignation not a comparison in the while loop. This means it will always be true.

Change it to:

while( ClickCount === true ){
    this.SearchClick();
    ClickCount = false;
}

Note the ===

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.