Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Navbar/next page button/page accessibility update for refactor #328

Merged
merged 5 commits into from
Jan 26, 2023

Conversation

jarmoza
Copy link
Contributor

@jarmoza jarmoza commented Jan 25, 2023

Closes #315 and #317

Some agent in the tool must be responsible for indicating that a page is accessible to the user (on the page via user action, or at some higher level like the navbar or layout, etc.) Previously, actions on a page by a user would manually change the accessibility status of the next page (via an action call to change pageData.<pageName>.accessible).

The navbar now keeps a watch on the store for changes, updating the accessible status of pages via updatePageDataAccessibility as the relevant changes are made to the store that would unlock them. This has the side effect of also keeping the next page button status on each page up to date with the state of the store.

The more complex Vuex getter isPageAccessible could not be reactive because it currently returns a boolean. Vue recalculates computed values based on whether or not values used in the computed function to create the return value have changed.. In the case of a primitive like a boolean with one return statement, isPageAccessible would only be calculated once. However, page accessibility state depends on multiple variables in the store depending on which page is being checked as accessible. Even a re-implementation of the function with multiple return statements does not produce the desired reactivity.

There are at least two methods for making sure that store changes trigger a check for page accessibility. The agent (in this case the tool-navbar component) can either place a watch on the specific store variables that may be involved in a state change OR it may deeply watch $store.state itself. (Suggestion for solution found here.)

This is accomplished via the placement of a watch in the created hook:

        created() {

            this.$store.watch(
                () => { return this.$store.state; },
                this.updatePageDataAccessibility,
                { deep: true }
            );
        },

The latter is the one implemented with this PR. A change in $store.state triggers a call to new store action updatePageDataAccessibility. The disabled attribute in the navbar and next page button are then simply tied to the pageData.<pageName>.accessible field which will always reflect the current state of the store.

@jarmoza jarmoza requested a review from surchs January 25, 2023 20:53
@surchs
Copy link
Contributor

surchs commented Jan 26, 2023

Hey @jarmoza, thanks for the PR. I think I'm either missing a piece of info or I disagree here. I'll quickly reply on your explanation.

Some agent in the tool must be responsible for indicating that a page is accessible to the user (on the page via user action, or at some higher level like the navbar or layout, etc.) Previously, actions on a page by a user would manually change the accessibility status of the next page (via an action call to change pageData.<pageName>.accessible).

Agree. My understanding is that the isPageAccessible getter replaces the pageData.<pageName>.accessible attribute.

The more complex Vuex getter isPageAccessible could not be reactive because it currently returns a boolean. Vue recalculates computed values based on whether or not values used in the computed function to create the return value have changed.. In the case of a primitive like a boolean with one return statement, isPageAccessible would only be calculated once. However, page accessibility state depends on multiple variables in the store depending on which page is being checked as accessible. Even a re-implementation of the function with multiple return statements does not produce the desired reactivity.

Agree about vue-computed reactivity in general (as in your link). But the isPageAccessible getter doesn't just return a boolean. There is a good bit of logic in it to decide whether a page is accessible or not, given the current store.state (I think you are even the one who wrote it) - and we're making sure that all changes we make to the store.state are done in a way that doesn't break reactivity. So any reactive update to the dependencies of isPageAccessible should trigger the getter to be recomputed. And we have been using getters in this way (i.e. relying on them to be reactive) in the past too and this fits with the docs. I did a quick experiment to use the getter directly and the app also behaves reactively - here is a patch that you can apply if you want to see what I'm talking about (didn't want to push to your PR branch).

Let me know if there is something else I'm missing about the getter, but if not, I would say let's use the getter we already have here and avoid adding the extra actions and watchers.

@jarmoza
Copy link
Contributor Author

jarmoza commented Jan 26, 2023

@surchs I think the short answer to this is that while I understand what you're saying the reactivity for isPageAccessible just does not work on my end. I will try out your code and let you know.

@jarmoza
Copy link
Contributor Author

jarmoza commented Jan 26, 2023

@surchs So, in summary. Your code "works" for the nav as does the current code in the dev branch. In fact, we can currently navigate between the pages using the appropriate nav item even though it appears disabled (gray). Hovering over the activated nav item reveals a finger pointer which allows a click and pass through to the next page.

There was just one more step to make it fully work – and that's the line you have added in your patch above. With the check to isPageAccessible in the getNavItemColor function, now the nav item correctly turns green (bootstrap color variant success).

So agreed with your changes in the patch. We no longer need the accessible flags in pageData in the store nor the watch solution I came up with as a workaround for the above. I will commit those changes now.

Copy link
Contributor

@surchs surchs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me @jarmoza. There is a mapActions left in the tool-navbar that can be removed. With that good to go 🎉!

@@ -52,6 +52,9 @@
// Fields listed in mapState below can be found in the store (index.js)
import { mapState } from "vuex";

// Allows for reference to store actions (index.js)
import { mapActions } from "vuex";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can be removed now as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @surchs. Will remove and merge.

@jarmoza jarmoza merged commit 3e86d0f into dev_components_talk_to_store_directly Jan 26, 2023
@jarmoza jarmoza deleted the jarmoza-315 branch January 31, 2023 16:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

2 participants