Prettier formatting a Vue component when I don't want it to - prettier

I've got Prettier configured to format on save.
I'm using a Vue component I got from npm to display data from an API.
<ExampleComponent
:aDynamicProp="foo"
dataset="bar"
/>
The prop dataset is required by the component.
The issue is Prettier wants to change dataset to data-set every time I save. I imagine because it thinks i'm trying to create a HTML data attribute.
As per Prettier docs i've tried adding <!-- prettier-ignore-attribute --> above the component but this doesn't seem to work (perhaps because I'm triggering formatting on save, or because it's a Vue template and not HTML?).
Can anyone shed light as to how I can force Prettier to ignore the prop?
Many thanks!

Add colon : to :dataset and that should do the trick, if it's just static string that's doing inside dataset then do :dataset="`my string`" with backtick (`). If you are getting data from data(){}, computed or from methods as mentioned below then just do :dataset="yourData":
export default {
data() {
return {
yourData: 'Your String'
}
},
// or
computed: {
yourData() {
return 'Your String'
},
},
// or
methods: {
yourData() {
return 'Your String'
},
},
};

Related

Vue3 force reset/clear of keep-alive components

I'm using keep-alive to maintain the state of a multi-step form in Vue3 so users can navigate back and forth as needed.
What I can't figure out, is how to force a clear of the cache. When users complete the form I give them an option to re-start and I currently clear the form submission object and return the users to page 1 of the form but keep-alive is preserving the form state so checkboxes are pre-selected. Is there a call I can make from my reset function to clear the keep-alive cache? Ideally for only some of the form steps, not all.
Hard to do.;) There's no built-in method to clear the keepAlive cache.
Looks like the form is not completely reseted but maybe could be enough to destroy the instance of components wrapped in
Are you using key="x" on the component that's wrapped with ? Like:
<KeepAlive>
<component key="x"/>
</KeepAlive >
reseting the key together with redirecting to 1st page could help.
But also to my mind came an idea that You maybe should re-initialize form initialData
ex:
<script>
const initialState = () => {
return {
name: '',
surename: '',
location: {
name: null,
},
};
};
export default {
data() {
return initialState();
},
methods: {
reset() {
Object.assign(this.$data, initialState());
},
},
};
</script>
let's dive into
https://learnvue.co/tutorials/vue-keep-alive
Found related issue:
https://stackoverflow.com/a/71766767/10900851
https://github.com/vuejs/vue/issues/6259#issuecomment-436209870
I actually ended up using an entirely different method and thought I would put it here in case it is of use to someone else.
I found it here: https://michaelnthiessen.com/force-re-render/
Basically, a reset of a component can be forced by changing its key value. This has the added benefit of letting you selectively force a re-render of any number of child components.
In the parent.
<PageOne :key="page_one_key">
<script>
export default {
...
data() {
return {
page_one_key: 0,
}
},
...
methods: {
myreset(){
this.page_one_key += 1;
}
}
}
</script>
If there are downsides to this approach I would love to know but it seems to work perfectly - allows back/forwards navigation of my form and selective resetting of the cached components.
It is also simple to implement.

vue testing vuetify input for disabled

I am very new to testing and I'm struggling my way through all this new stuff I am learning. Today I want to write a test for a vuetify <v-text-field> component like this:
<v-text-field
v-model="user.caption"
label="Name"
:disabled="!checkPermissionFor('users.write')"
required
/>
my test should handle the following case:
an active, logged in user has a array in vuex store which has his permissions as a array of strings. exactly like this
userRights: ['dashboard', 'imprint', 'dataPrivacy']
the checkPermissionFor() function is doing nothing else then checking the array above with a arr.includes('x')
after it came out the right is not included it gives me a negotiated return which handles the disabled state on that input field.
I want to test this exact scenario.
my test at the moment looks like this:
it('user has no rights to edit other user overview data', () => {
const store = new Vuex.Store({
state: {
ActiveUser: {
userData: {
isLoggedIn: true,
isAdmin: false,
userRights: ['dashboard', 'imprint', 'dataPrivacy']
}
}
}
})
const wrapper = shallowMount(Overview, {
store,
localVue
})
const addUserPermission = wrapper.vm.checkPermissionFor('users.write')
const inputName = wrapper.find(
'HOW TO SELECT A INPUT LIKE THIS? DO I HAVE TO ADD A CLASS FOR IT?'
)
expect(addUserPermission).toBe(false)
expect(inputName.props('disabled')).toBe(false)
})
big questions now:
how can I select a input from vuetify which has no class like in my case
how can I test for "is the input disabled?"
wrapper.find method accepts a query string. You can pass a query string like this :
input[label='Name'] or if you know the exact index you can use this CSS query too : input:nth-of-type(2).
Then find method will return you another wrapper. Wrapper has a property named element which returns the underlying native element.
So you can check if input disabled like this :
const buttonWrapper = wrapper.find("input[label='Name']");
const isDisabled = buttonWrapper.element.disabled === true;
expect(isDisabled ).toBe(true)
For question 1 it's a good idea to put extra datasets into your component template that are used just for testing so you can extract that element - the most common convention is data-testid="test-id".
The reason you should do this instead of relying on the classes and ids and positional selectors or anything like that is because those selectors are likely to change in a way that shouldn't break your test - if in the future you change css frameworks or change an id for some reason, your tests will break even though your component is still working.
If you're (understandably) worried about polluting your markup with all these data-testid attributes, you can use a webpack plugin like https://github.com/emensch/vue-remove-attributes to strip them out of your dev builds. Here's how I use that with laravel mix:
const createAttributeRemover = require('vue-remove-attributes');
if (mix.inProduction()) {
mix.options({
vue: {
compilerOptions: {
modules: [
createAttributeRemover('data-testid')
]
}
}
})
}
as for your second question I don't know I was googling the same thing and I landed here!

apollo react: proper way to switch a query's params

In my app I have a sidebar with a list of "saved searches" and a central area that should show the results of a search. Whenever I click on a saved search link, I want to update the central area with the results of that search.
What is the proper way to do this with apollo-react?
I tried with this:
// SidebarConnector.js:
const withVideoSearch = graphql(
VIDEO_SEARCH_QUERY,
{
name: 'videoSearchQuery',
props: ({ videoSearchQuery }) => {
return ({
searchVideos: videoSearchQuery.refetch,
});
},
}
);
export default withVideoSearch(Sidebar);
My saved searches are doing a searchVideos({ query: "some query" }) on click which, based on the above, is doing a refetch for the VIDEO_SEARCH_QUERY query with different variables.
This works fine, the call is made to the graphql server and results are returned just fine.
For the main component that shows the list of results I use:
export default graphql(VIDEO_SEARCH_QUERY)(ResultList);
Initially the main component gets its results from the server as if the query was done without variables which is fine, exactly how I want it.
The problem is that every refetch seems to create a different entry in ROOT_QUERY in apollo's store and my main component is "locked" into the one without variables.
Here's what apollo's store looks like after the initial fetch and one of the refetches triggered from a saved search:
ROOT_QUERY
searchVideos({"query":"coke"}): [Video]
0:▾Video:arLaecAu5ns
searchVideos({"query":null}): [Video]
0:▾Video:3HXg-oVMA0c
So my question is how to either switch the main component to the "current search" or how to overwrite the store on every refresh so that there's only one key so the main component updates correctly.
For completeness here's my VIDEO_SEARCH_QUERY:
export const VIDEO_SEARCH_QUERY = gql`
query searchVideos($query: String) {
searchVideos(query: $query) {
...fVideo
}
}
${fVideo}
`;
Maybe I'm misunderstanding your use case, but it seems like there's no need to utilize refetch here. It would be simpler to persist whatever the selected search string is as state, pass that state down as a prop to your main component and then just use that prop as the variable in your GraphQL request. So the graphql call inside your ResultList component would look something like this:
const options = props => ({ variables: { query: props.searchString } })
export default graphql(VIDEO_SEARCH_QUERY, { options })(ResultList);
Then just have your onClick handler for each saved search set the state to whatever that search string is, and Apollo will do the rest. This is super easy with Redux -- just fire off the appropriate action. If you're not using Redux, you may have to lift the state up so it can then be passed down as a prop, but the concept is the same.

Ionic2: invalid page component: ProjectInfoPage

export class ProjectDetail {
page: string;
}
the page info contained in json, like this:
{
"data":[
{
page: "PageInfoPage"
},
{
page: "PageInfoPage1"
}
]
}
I parse info from this json,then saved in Array.
when execute this.nav.push(pd.page),throw exception as title described.I don't know how to convert 'string' to 'component'.
============================================================
I use the method like Angular 2 - Resolve Component Factory with a string described. This is my code:
itemClick(pd: ProjectDetail) {
var factories = Array.from(this.resolver['_factories'].keys());
var factoryClass = <Type<any>>factories.find((x: any) => x.name === pd.page);
const factory = this.resolver.resolveComponentFactory(factoryClass);
const compRef = this.vcRef.createComponent(factory);
if (this.componentRef) {
this.componentRef.destroy();
}
this.componentRef = compRef;
this.nav.push(compRef, {
item: pd,
pid: this.project.pid
});
}
it still does not work.Thank you for your answer.
At last,I solved it with a stupid method.As I create a map like this:
componentRegistry = {
'ProjectInfoPage': ProjectInfoPage
};
And then push like this:
this.nav.push(this.componentRegistry[pd.page], {
item: pd,
pid: this.project.pid
});
Normally, you have to import the actual component class for the page that you want to navigate to and then push that class onto the stack. By default, there is no way built into ionic2 to navigate via string references. I had the same problem today where I wanted to be able to navigate using strings rather than pushing the component class on the stack.
Check out the following link from the ionic forums on how to accomplish this. Look at the last two responses to the thread, which include how to solve this problem from beta stages and then an updated answer for how to do so with ionic 2.2.0. Although I'm pretty sure the same solution will work for all versions of ionic 2 since final release.
https://forum.ionicframework.com/t/ionic2-navigation-circular-depencies/41123/5

Sublimelinter & JSHint complaining about Facebook's Open Graph objects {og:url: "example.com"}

I'm using JSHint and SublimeLinter with Sublime Text 3, but when using Facebooks API it doesnt like the object double : in the structure, eg. { og:url: 'example.com' }
FB.api(
'me/objects/my-app:object',
'post',
{
og:url: http://samples.ogp.me/12345678910,
og:title: Sample Object,
og:type: my-app:object,
og:image: https://fbstatic-a.akamaihd.net/images/devsite/attachment_blank.png,
og:description: ,
fb:app_id: 12345678910,
place:location:latitude: Sample Location: Latitude,
place:location:longitude: Sample Location: Longitude
},
function(response) {
// handle the response
}
);
I know how to ignore certain variables and names in the .jshintrc file on the root of my project, but not sure how to stop it complaining about this structure. I thought since the Facebook API is popular it's worth posting it here.
Wrap them in quotes.
eg. { 'og:url': 'example.com' }