I have multiple templates in my project, with a fairly simple url structure.
/startpage/
/startpage/test_1
/startpage/test_2
In my 'App.vue' I made a template, which is shown on every page in my project. That template includes a button, which is supposed to act like a 'Home' button, named 'Projects'.
App.vue
<template>
<div>
<div>
<router-link :to="/startpage/"><button class="Project">Projects</button></router-link>
</div>
<router-view/>
</div>
</template>
When I'm on the startpage (localhost:4545/#/startpage/), the button has the target localhost:4545/#/startpage/.
But when I'm on another page, for example localhost:4545/#/startpage/test_1, the button suddenly has the same url as the page I'm on.
Why does the router change the link dynamically and not keep the target /startpage/?
As described in the documentation, you either need to use binding or not:
<!-- literal string -->
<router-link to="home">Home</router-link>
<!-- renders to -->
Home
<!-- javascript expression using `v-bind` -->
<router-link v-bind:to="'home'">Home</router-link>
<!-- Omitting `v-bind` is fine, just as binding any other prop -->
<router-link :to="'home'">Home</router-link>
So it should be that you don't need to use :, or use a string literal. Currently it tries to use it as a variable, which of course it not present.
Related
My Question
I have a Vue component that renders content like so:
<template>
<div class="item">
<h1>{{ title }}</h1>
<p>{{ contents }}</p>
<!-- Lot's of other stuff... -->
</div>
</template>
<script>
// export default...
</script>
<style lang="scss">
// style...
</style>
Note the contents within the div...
In some circumstances, I need to change <div class="item"> to <a class="item">. With that in mind, is there a way to conditionally change the tag (e.g. a, div) for the root element of a Vue component?
Research
I have searched around online and was able to find something about using the render function like so:
render (createElement) {
return createElement(this.tag, {}, this.$slots.default);
}
The issue I have with the above is that it implies that I need two separate components, for example; Item.vue and ItemTag.vue. Surely there is a way to do this with one component?
I believe you could use is:
<div :is="useA ? 'a' : 'div'">
...
</div>
This isn't quite what the docs suggests it's for but it does seem to have the desired effect.
https://v2.vuejs.org/v2/api/#is
Using a render function instead wouldn't necessarily require you to have two components but it would need you to rewrite your entire template as a render function.
I am building app using laravel and vue. I have navbar, currently it looks like:
<template>
<nav class="navbar">
<p>{{msg}}</p>
</nav>
</template>
And I use it like here:
<body class="">
<div id="app">
<div class="">
<navbar></navbar>
#yield('content')
</div>
</div>
</body>
In yield I am loading another components, so I have navbar and another component together. Now I want to override that {{msg}} variable from navbar in another components. In every component that variable will be diferent.
I do not know how to override it in components and from {{msg}} do some text. Can you help me? (That code above is all what I have)
If you want to use msg in other components, then you need to use prop
Use like:
props: ['msg'],
Then, you need to bind it like:
<component-name :msg="msg"></component-name>
In your component, you can take it like:
<template>{{ msg }}</template>
Hope you understand!
Components can be communicate with props. You can transfer the data to another components and you can use if statement.
https://v2.vuejs.org/v2/guide/components.html#Props
I'd like to have Vue custom components loaded only after the route has been clicked.
Let's say my app's stripped down html structure looks like this:
<div id="admin">
<admin-menu><!-- component with routes --></admin-menu>
<div id="content-container">
<!-- want dynamically loaded Single Page Components here -->
</div>
</div>
I'd like content container to be the target, where the dynamically loaded Single Page Components should be placed.
The one thing I don't want is to predefine the custom components in the content container right from the start like this:
<div id="admin">
<admin-menu><!-- component with routes --></admin-menu>
<div id="content-container">
<my-component-1></my-component-1>
<my-component-2></my-component-2>
<my-component-3></my-component-3>
<my-component-N></my-component-N>
</div>
</div>
If I do that, they must be registered i.e. loaded when vue hits them on startup of the app and but I'd like the components to be lazy loading.
So how can I initialize and place a single file component in the target content-container only after the respective router link has been clicked?
Ember Community Assemble!
I want to conditionally {{render ''}} small templates inside of the application.hbs sidebar but the content of that sidebar depends on which model's hbs we are routed to. For instance, the contents of the 'permit' sidebar would be different than that of the 'profile' sidebar.
Right now I am only able to render all of the sidebar contents at once regardless of what model.hbs is chosen.
<!-- Right Sidebar in application.hbs START -->
<div id="sidebar-wrapper" class="super-super-float-right-col">
<div id="sidebar-wrapper" class="super-float-right-col">
<div id="sidebar-wrapper" class="float-right-col">
{{render 'applicant'}} <!-- only available to '/person/#' -->
{{render 'location'}} <!-- only available to '/permit/#' -->
</div>
</div>
</div>
<!-- Right Sidebar END -->
<div class="The rest of the content">
{{outlet}} <!--inserts the rest of the html into the main content container -->
</div>
I don't want both 'applicant' and 'location' to be rendered at the same time as they are above, and I want to data inside of 'applicant' to change depending on the id # of 'person'. The same relationship applies to 'location' inside of 'permit.hbs'
VpcYeoman.PermitRoute = Ember.Route.extend({
renderTemplate: function() {
this.render({ render:'location'});
}
});
Application_route.js is blank for now
Although 1.2.0 introduced the ability to use properties for template name in {{view}} it does not work for {{render}} yet.
So your options are to use {{view}} if you can, or a series of {{#if}} in the template, or a component/view to wrap the choice of what to render (one way to do this would be to have a template for each render, and a choice view that binds templateName property to the parentController property that determines which should be displayed)
Here is a jsbin that I used to experiment.
I have a common html structure in my app.html in order to apply for all pages:
<template>
<require from="header"></require>
<require from="side-bar"></require>
<require from="theme-panel"></require>
<require from="footer"></require>
<!-- BEGIN HEADER -->
<js-header></js-header>
<!-- END HEADER -->
<div class="clearfix"></div>
<!-- BEGIN CONTAINER -->
<div class="container">
<div class="page-container">
<!-- BEGIN SIDEBAR -->
<js-side-bar></js-side-bar>
<!-- END SIDEBAR -->
<div class="page-content-wrapper">
<div class="page-content">
<!-- BEGIN STYLE CUSTOMIZER(optional) -->
<js-theme-panel></js-theme-panel>
<!-- END STYLE CUSTOMIZER -->
<!-- BEGIN ACTUAL CONTENT -->
<div class="fade-in-up">
<router-view></router-view>
</div>
<!-- END ACTUAL CONTENT -->
</div>
</div>
</div>
<!-- BEGIN FOOTER -->
<js-footer></js-footer>
<!-- END FOOTER -->
</div>
<!-- END CONTAINER -->
</template>
However, in my case, i have a login page with a totally different structure compared to others. In my app.js, i tried to use getViewStrategy() method to control which views i will render as following:
activate(params, routeConfig, navigationInstruction){
this.navigationInstruction = navigationInstruction;
//console.log("params", params); // undefined
//console.log("routeConfig", routeConfig); // undefined
//console.log("navigationInstruction", navigationInstruction); // undefined
//console.log("router", router); //undefined
}
getViewStrategy(){
if(this.navigationInstruction == 'login'){
return "app_login.html";
} else {
return "app.html";
}
}
in the code above, 'navigationInstruction' is undefined. Therefore, my solution cannot work well. Does anybody have another solution? Thanks so much!
Great question. In fact, when you have two totally sections of the same single page application, the right thing to do is create multiple root view models, or shells.
First, set your app up for custom initialization by adding aurelia-app="main" to your body tag, and creating a new initialization file correspondingly named main.js. It should look like this.
export function configure(aurelia) {
aurelia.use
.standardConfiguration()
.developmentLogging();
// notice that we are setting root to 'login'
aurelia.start().then(app => app.setRoot('login'));
}
The app.setRoot('login') line tells Aurelia to load a file called login.js as the app root. This file should look similar to your current app.js. You can do anything you want in this file and it's corresponding view, and it will stay totally separate from your main app.
To navigate back to your main app, you'll need to call app.setRoot('app'), which means you'll need to inject the Aurelia object into your Login view model.
import { inject, Aurelia } from 'aurelia-framework';
#inject(Aurelia)
export class Login {
constructor(aurelia) {
this.aurelia = aurelia;
}
goToApp() {
this.aurelia.setRoot('app');
}
}
For more information, see my full write-up here: Aurelia Login Best Practices
Try adding 'if' bind at the top of the sections select the page style you want based on the view model variable set during 'canActivate()' or 'activate()' process of each page.
<template>
<template if.bind = "normalMain">
....
</template>
<template if.bind = "loginScreen">
....
</template>
</template>