I got div with if.bind working as was suggested in this question: Using literal JavaScript values in an Aurelia view. But then I noticed that showTemplate on viewModel is being constantly checked by framework, about 10 times per second. The stack is following:
execute._prototypeProperties.visible.get (welcome.js:29)
getValue (dirty-checking.js:93)
isDirty (dirty-checking.js:127)
check (dirty-checking.js:63)
(anonymous function) (dirty-checking.js:49)
Is it supposed to be like this? Seems to be not very resource-friendly.
Best regards, Eugene.
Aurelia uses Object.observe for simple Javascript properties. If showTemplate is a function or a getter/setter, then Aurelia currently reverts to dirty checking. This can be removed by declaring the dependencies of the function. This is outlined here: https://github.com/aurelia/binding/pull/41
I have created a version of the Aurelia Skeleton project that implements this: https://github.com/ashleygrant/skeleton-navigation/tree/declare_dependencies
To implement this, you must switch to using the aurelia-main attribute. Add a main.js file:
import {LogManager} from 'aurelia-framework';
import {ConsoleAppender} from 'aurelia-logging-console';
import {ComputedObservationAdapter, ObjectObservationAdapter} from 'aurelia-framework';
LogManager.addAppender(new ConsoleAppender());
LogManager.setLevel(LogManager.levels.debug);
export function configure(aurelia) {
aurelia.use
.defaultBindingLanguage()
.defaultResources()
.router()
.eventAggregator();
aurelia.container
.registerSingleton(ObjectObservationAdapter, ComputedObservationAdapter);
aurelia.start().then(a => a.setRoot('app', document.body));
}
Then, in welcome.js, add the following import statement:
import {declarePropertyDependencies} from 'aurelia-framework';
and then outside the Welcome class, add the following method call:
declarePropertyDependencies(Welcome, 'fullName', ['firstName', 'lastName']);
Related
I need to modify 'preConfigureProduct' function under vuestorefront/core/modules/catalog/helpers/search.ts
https://github.com/vuestorefront/vue-storefront/blob/hotfix/v1.12.3/core/modules/catalog/helpers/search.ts#L51
I need to do the customisation based on my client requirement. Thus I need to override this function in my project.
But there is no document about how to override one function from helper. I am also new in vue storefront, so I dont fully understand module extending or mixins.
Thanks in advance.
I have figured out by myself, I will leave a short answer for who is stuck as well.
Additionally, I am not really sure it is a good practise, if you know a better way, leave it here please.
From what I understood is if you need to overwrite one function from helper, you also need to 'overwrite' the function which called your helper function.
In my case, I need to overwrite function preConfigureProduct , from module catalog helper.
The function called this preConfigureProduct is one asyc function configureProducts from module catalog-next, https://github.com/vuestorefront/vue-storefront/blob/hotfix/v1.12.3/core/modules/catalog-next/store/category/deprecatedActions.ts#L22.
(I know it is deprecatedActions. It is my next job to figure out how to switch to new ones)
Thus, I extended module catalog-next, and literally copy paste configureProducts(because I dont need to modify it), but import preConfigureProduct to my new file.
import { preConfigureProduct } from './helpers/search'
my new search.ts file:
import Vue from 'vue';
import config from 'config';
export const preConfigureProduct = ({ product, populateRequestCacheTags }) => {
.....
return product;
};
That is it !
Hopefully it helps others.
If there is any mistake, welcome to point it out.
In other to avoid multiple imports into my vuejs app I created an index.js file and imported all the files in it like so:
import AddMember from "./AddMember.vue";
import EditMember from "./EditMember.vue";
export {
AddMember,
EditMember,
};
Then in my component compenent I imported them like so:
import * as Members from "../members/index.js";
export default {
name: "members-table",
components: {
AddMember: Members.AddMember
EditMember: Members.EditMember,
},
}
The EditMember Component is a dialog that opens up per the member clicked. But Anytime I click on a member on a the table I get and error that looks like this: even though the name prop was defined in all the components.
Unknown custom element: <edit-member> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
I resolved the problem my importing the EditMember.vue file itselfimport EditMember from './EditMember';. My question however, is there a way I can achieve this. Or better still what I'm I missing or did wrong.
well if it`s reusable components your trying to do so wouldnt it be better to create base components? and then you dont need to import them each time?
import { AddMember, EditMember } from "../members/index.js"; this should work like #Asimple said
Maybe you can try to import them separately?
Like this:
import { AddMember, EditMember } from "../members";
Update:
Changed import source, please, try it.
Working example here
Try this, you may need to create alias as:
components: {
'AddMember': Members.AddMember, // use single quotes
'EditMember': Members.EditMember,
},
When you inspect a Vue component that you have imported, you will get something like this:
import ClickB from 'ClickB.vue';
console.log(ClickB);
I have seen that nuxt adds a custom property there (called _nuxt), just like there is _ssrRegister. I have 2 questions:
How is it possible to add properties to the component?
Can you pass that property from the component to its instances?
It is simple. Just decorate Vue prototype like this to add instance method:
import Vue from 'vue';
// Adding an instance method
Vue.prototype.$someMethod = function (methodOptions) {
// Your own logic...
}
As a good practice, this code should be in your index.js or main.js file. Taking it one step further, you should put this code inside plugins as explained in Vue documentation for plugins.
You can always just add them to your definition and to access them you would use $options instance property.
Ref: https://v2.vuejs.org/v2/api/#vm-options
I'm having some trouble passing attributes into a custom component. I have tried declaring my component the following ways:
<require from="../components/project-documents"></require>
<project-documents projectId="testing123"></project-documents>
<project-documents projectId.bind="project.Name"></project-documents>
import {customElement, bindable} from "aurelia-framework";
import {autoinject} from "aurelia-dependency-injection";
#customElement("project-documents")
export class ProjectDocuments {
#bindable projectId:string;
attached() {
alert(this.projectId);
}
}
When the alert is called, undefined is the value I get from it. Also, is the customElement decorator required?
Instead of using camelCase for your attributes, try dash-case.
Try this:
<project-documents project-id="testing123"></project-documents>
<project-documents project-id.bind="project.Name"></project-documents>
According to aurelia conventions, dash-case'd attributes will be converted to camelCase variables in your ViewModel, so your VM is already fine.
I'm trying to use humane.js with aurelia however I'm running in a problem.
It appears humane.js adds an element to the DOM when it's created and so far the only way I've found to do it is to force it like this....
showMessage(message) {
this.notify = humane.create();
this.notify.log(message);
}
However this creates a new instance of humane every time showMessage() is called. This breaks the queue as each one is rendered separately.
I've tried putting the create() in the activate() method of the view model but that doesn't seem to work either.
Any ideas?
This solved the problem, I've created a custom element for humane that is then included in app.html in the same way loading-indicator is in the skeleton app.
import humane from 'humane-js';
import 'humane-js/themes/original.css!';
import {inject, noView} from 'aurelia-framework';
import { EventAggregator } from 'aurelia-event-aggregator';
import { ApiStatus } from 'resources/messages';
#noView
#inject(EventAggregator)
export class StatusIndicator {
constructor(ea) {
this.ea = ea;
ea.subscribe(ApiStatus, msg => this.showMessage(msg.apistatus));
}
attached() {
this.humane = humane.create();
}
showMessage(message) {
this.humane.log(message);
}
}
The important part was the attached() this allows the setup of humane to work correctly.
Unfortunately for Aurelia, Humane will attach itself to the DOM automatically as a child of body, which Aurelia then replaces.
There is a really, really, simple fix for this:
Change your:
<body aurelia-app="main">
To this:
<body><div aurelia-app="main">
This way, Aurelia doesn't replace the div which is in body, you don't need to worry about attached() or where the import appears in your code, and humane works perfectly.
I have raised a humane github issue for this. https://github.com/wavded/humane-js/issues/69
Here is how I am using humane.js with Aurelia:
1) I load the CSS in the app index.html.
2) In each view model that requires humane, I import humane
import humane from 'humane-js/humane';
I do NOT inject human into the view model.
3) I show notifications like this:
humane.log('Error:, { addnCls: 'humane-libnotify-error' });
I hope this helps you.