How to build Vue.js links in a separate div? - vue.js

I want to create a static header, with some links that change a vue app like a SPA. I know how to do this within the main app, but how can it be achieved outside of it, in a static header for example?
App being the main vue instance.
<body>
<div id="header">
</div>
<div id="#app"></div>
</body>

As claimed in the comments you can simply put your static header inside your app
<div id="#app">
<!-- static -->
<div id="header">
<router-link to="" id="link_to_change_app_view" />
</div>
<!-- dynamic -->
<router-view></router-view>
</div>

Related

Using a component inside another component in VueJS

While I was reviewing headlessui's menu component, I saw the use of 2 components that are nested like the following: (see: https://headlessui.dev/vue/menu)
<template>
<Menu>
<MenuButton>More</MenuButton>
<MenuItems>
<MenuItem v-slot="{ active }">
// some content
</MenuItem>
</MenuItems>
</Menue>
</template>
So as you may see, there is a MenuItem component inside of the MenuItems component. And I need something similar to that so I can use a template and put another component's result into that template.
Here the example of what I am trying to do:
<!-- HeadingComponent.vue -->
<div class="group">
<div class="head">
{{ title }} <button>Create New</button>
</div>
<div class="content">
<!-- I want to put some component's rendered content here -->
</div>
</div>
And this is, let's say, a page where I want to use the common component.
<!-- Blog.vue -->
<HeadingComponent :title="Posts">
<BlogPostsComponent :post="someArray"/> <!-- Some other component which may vary -->
</HeadingComponent>
The question
What kind of changes do I need to do in the component HeadingComponent.vue so it works as I expected?
Slots are a good way to add a component to another or even simple html
docs : https://fr.vuejs.org/v2/guide/components-slots.html
<h1>Vue JS Slots Application</h1>
<div id="app">
<slots>
<template slot="slotA"><pre>Slot A Content from parent.</pre></template>
<template><i>Parent Component Content.</i></template>
</slots>
<hr/>
<slots>
<template slot="slotB">Replace Slot B Default Content</template>
<template><b>Replace Default Slot Content.</b></template>
</slots>
</div>
<template id="aside">
<div>
<h3>My Slots App</h3>
<slot>Default Slot Content</slot><br>
<slot name="slotA"></slot><br>
<slot name="slotB"></slot><br>
</div>
</template>
Example of codepen :
https://codepen.io/brian_kim/pen/NpWKGe
Just in a short time, I found something like slots in VueJS which is definitely what I was looking for.
Here is the guide page:
https://v2.vuejs.org/v2/guide/components-slots
What I did in my problem is that I put <slot></slot> tags inside div whose class is content, and then the last sample I gave (Blog.vue) has worked.
<!-- HeadingComponent.vue -->
<div class="group">
<div class="head">
{{ title }} <button>Create New</button>
</div>
<div class="content">
<!-- I want to put some component's rendered content here -->
<slot></slot>
</div>
</div>

Portal-Vue: How to use MountingPortal?

I like to use MountingPortal to teleport an element (later a Component) to <body>. But the element is not moved to the target.
Setup
Create a Vue app with vue create portal-test and choose Vue 2 and all defaults
Add Vue-Portal: npm install --save portal-vue
Edit main.js: add import PortalVue from 'portal-vue' and Vue.use(PortalVue)
In packages.json under "dependencies" I've found "portal-vue": "^2.1.7",
Add portal target in public/index.html
In the body I add a div with id target-id that should be treated as a portal target:
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<hr />
<div id="target-id">
Hey
</div>
<hr />
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
Change App.vue
<template>
<div id="app">
<MountingPortal name="destination" mountTo="#target-id">
</MountingPortal>
<portal to="destination">
<p>This should be rendered outside</p>
</portal>
</div>
</template>
Expected output
The <p>This should be rendered outside</p> should displayed between the two <hr />.
Actual output
The <p>...</p> is missing in the DOM. I've tested in Firefox and Edge, the DOM looks the same.
Ah, ok, a <portal-target> must be wrapped in <MountingPortal>.
This works:
<template>
<div id="app">
<MountingPortal mountTo="#target-id">
<portal-target name="destination" />
</MountingPortal>
<portal to="destination">
<p>This should be rendered outside</p>
</portal>
</div>
</template>

Materialize Model - Content underneath is visible

I'm using Materialize to generate modals on a php website, only the data below is clearly visible.
This is based on data from a MySQL database. For each hard drive in said db, generate a card and populate with drive data.
For testing purposes I removed all php code to see if that was what was breaking it, sadly I still had normal text punch through.
Any ideas? Are there css options I can use to force the opaque settings? Or maybe an alternative altogether, I did have a look at css overlays but had the same problem.
In the code below I've removed all php. The complete website source code can be found at my repo
here (albeit without the modal stuff as not committed to master yet)
<div class="card">
<div class="card-image waves-effect waves-block waves-light">
<!-- Drive stats on index -->
<div class="card-content center">
<h6>Hard Drive Canonical Name Goes Here via PHP</h6>
<ul>
<li>Hard Drive Size Goes Here Via PHP</li>
<li>Hard Drive Temp Goes Here via PHP</li>
<li> </li>
<li>Last updated at database timestamp goes here via PHP</li>
</ul>
</div>
<div class="container center">
<a class="waves-effect waves-light btn blue darken-1 modal-trigger" href="#modal">Launch Temperature History</a>
<div id="modal" class="modal">
<div class="modal-content">
<div class="card graphcolour">
<div class="card graphcontent">
<canvas id=1></canvas> <!-- <?php echo htmlspecialchars( $drive['DiDriveId'] )?> is what would normally be in here -->
</div>
</div>
"hello there!"
</div>
<div class="modal-footer">
Close
</div>
</div>
</div>
<script>
$(document).ready(function(){
$('.modal').modal();
})
</script>
<!-- Status Images -->
<!-- Images would go here based on PHP if else statements -->
</div>
</div>
The materialize modal code snippets were edited versions of below:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.min.css">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<script type = "text/javascript" src = "https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
</head>
<body>
<div class="container">
<h3>A Demo of Modal</h3>
<!-- Modal Trigger -->
<a class="waves-effect waves-light btn pink darken-1 modal-trigger" href="#demo-modal">Launch Modal</a>
<!-- Modal Structure -->
<div id="demo-modal" class="modal">
<div class="modal-content">
<h4>A Demo of Simple Modal</h4>
<p>Content of the modal goes here. Place marketing text or other information here.</p>
</div>
<div class="modal-footer">
Close
</div>
</div>
</div>
<script>
$(document).ready(function(){
$('.modal').modal();
})
</script>
</body>
</html>
Thanks to SeanDoherty for clarifying what I felt was the answer. I moved the Modal outside of the card, added three empty line breaks to the bottom of my card, then re-added the modal script with css offsetting. It's cheap, but it works!
.modalPosition{
top: -100px;
}

how to use <slot>, who can give me a sample demo?

I'm learning Vue framework, could not understand how to use slot, who can show me a sample demo please?
thanks a lot.
#Doc thank you for your answer and prompt. And i make out the demo:
<!DOCTYPE html>
<html>
<head>
<title>39、slot !</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<alert-box>
Something bad happened.
</alert-box>
</div>
<script>
Vue.component('alert-box', {
template: `
<div class="demo-alert-box">
<strong>Error!</strong>
<slot></slot>
</div>
`
})
var app = new Vue({
el:'#app'
})
</script>
</body>
</html>
As a quick code example from https://v2.vuejs.org/v2/guide/components-slots.html#Named-Slots
Lets say you want to render the given template called 'base-layout'
<div class="container">
<header>
<!-- We want header content here -->
</header>
<main>
<!-- We want main content here -->
</main>
<footer>
<!-- We want footer content here -->
</footer>
</div>
So you can see we have three slots 'header', 'main' and 'footer'.
If you write
<base-layout>
<h1 slot="header">Here might be a page title</h1>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<p slot="footer">Here's some contact info</p>
</base-layout>
Then the first h1 tag value goes inside the slot named 'header' in our template.
And similarly other values.
The result would be
<div class="container">
<!-- this is where the 'header' slot was -->
<h1>Here might be a page title</h1>
<!-- this is where the main slot was -->
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<!-- this is where the footer slot was -->
<p>Here's some contact info</p>
So slots are basically like placeholder which can be named and you can send information at exact part.

How to use Masonry grid layout in vuejs2(with bootstrap) without jquery?

I want to display tweets like card-columns in my page.
I am not able to use Masonry in my vue webpack template. i have used tried it through npm & CDN but not getting grid properly.
in main.js
import Tweet from 'vue-tweet-embed';
import Masonry from 'masonry-layout';
in html
<head>
//....
<script src="https://unpkg.com/masonry-layout#4/dist/masonry.pkgd.min.js"></script>
</head>
in template
<div class="grid">
<div class="grid-item" v-for="i in topics">
<Tweet class="" :id="i.tweets.quoted_status_id_str" :options="{ theme: 'light' }" error-message-class="text-center text-muted tweet_err"><div class="text-center text-muted card" style="margin-top:12px;min-width:30px;"><i class="ion-social-twitter"></i>Loading tweet...</div></Tweet>
</div>
</div>
I have used vue-masonry.
(We need to take care of redraw method this.$redrawVueMasonry(); on update or change.)