Component not rendering when using vue-template - templates

I have the following...
main.vue
<template>
<div>
<header></header>
</div>
</template>
<script>
export default {}
</script>
header.vue
<template>
<div>{{ message }}</div>
</template>
<script>
export default {
data: () => {
return {
message: 'Dashboard'
}
}
};
</script>
main.js
import Vue from 'vue';
import Header from './header.vue'
import App from './main.vue'
Vue.component("header", Header);
new Vue(App).$mount('#km-viewport')
But when I run this the header component is never rendered. What am I missing? Does using the vue-template webpack plugin require something special here?
I have looked at a couple similar stack overflows and I have tried to use components: { Header } instead but that still doesn't work.
I also tried...
main.vue
<template>
<div>
<header></header>
</div>
</template>
<script>
import Header from './header.vue'
export default {
components:{
"header": Header
}
}
</script>
header.vue
<template>
<div>{{ message }}</div>
</template>
<script>
export default {
data: () => {
return {
message: 'Dashboard'
}
}
};
</script>
main.js
import Vue from 'vue';
import App from './main.vue'
Vue.component("header", Header);
new Vue(App).$mount('#km-viewport')

Yours is a frequent problem:
[Vue warn]: Do not use built-in or reserved HTML elements as component id: name
In your case <header> is a reserved HTML element.
The same happens to <main>, <article> and so on.
Solution: Rename your header component to other name.
Example (I renamed header to header2):
main.vue
<template>
<div>
<header2></header2>
</div>
</template>
<script>
import Header from './header.vue'
export default {
components:{
"header2": Header
}
}
</script>
header.vue
<template>
<div>{{ message }}</div>
</template>
<script>
export default {
data() {
return {
message: 'Dashboard'
}
}
};
</script>
Bonus: Don't use arrow functions as in data: () => {, that will give you problems. Use like data() {. This rule applies to methods, computeds, watchers and all other Vue instance options.

Related

Django Templates with Vue

I'm trying to integrate vue-components into django-templates. The basic setup did work, but I'm stacked with a component which needs an import itself.
Here is the component (vue/dropdown.html):
<div id="app">
<template>
...
</template>
</div>
<script setup>
import { computed, ref } from 'vue'
import {CheckIcon, ChevronUpDownIcon} from '#heroicons/vue/20/solid'
const query =ref('')
const selectedPerson = ref(null)
...
var app = new Vue({
delimiters: ['[[', ']]'],
el: '#app',
data: {
message: 'Hello Vue!',
},
});
</script>
So, the 2 imports:
import {computed, ref} from Vue
import {CheckIcon, ChevronUpDownIcon} from '#heroicons/vue/20/solid'
are triggering the error in the browser's console:
Cannot use import statement outside a module
What is the proper way to use the imports?
I'm calling the dropdown.html from base.html:
<html lang="{{ LANGUAGE_CODE }}">
<head>...</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
{% include 'vue/dropdown.html' %}
</body>
</html>
I think this happens because vue cdn should be imported into dropdown.html.Please try this fix and let me know if it works.
Thank you

vuejs + drf - unable to get data from drf api in vuejs using http/axios

Image of vuejs folder structure
Unable to get data in Vue js from drf api using http / axios ? I am not getting any error also
App.vue:
<template>
<div id="app">
<div id="show-blogs">
<h1>Mgmt View's</h1>
{{ info }}
</div>
<ul v-if="errors && errors.length">
<li v-for="error of errors">
{{error.message}}
</li>
</ul>
<router-view/>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'App',
data () {
return {
info: ""
}
},
created() {
axios.get('http://127.0.0.1:8000/management/api/list/').then(response=> {
this.info = response.data
})
.catch(e => {
this.errors.push(e)
})
}
}
</script>
Here I provide the code of App.vue, rest all file I have not change anything

How to share settings across an application?

I have a main page listing some categories / subcategories. Whenever a subcategory is clicked, the action openSubcategory is triggered:
// routes/application.js
import Ember from 'ember';
export default Ember.Route.extend({
userSelections: Ember.inject.service('user-selections'),
actions: {
openSubcategory: function(categoryId, subcategoryId) {
var userSelections = this.get('userSelections');
userSelections.set('category', categoryId);
userSelections.set('subcategory', subcategoryId);
this.transitionTo('filter-categories');
},
}
});
To pass the selections to the corresponding controller, I am using a service:
// services/user-selections.js
import Ember from 'ember';
export default Ember.Service.extend({
category: null,
subcategory: null,
init() {
this._super(...arguments);
this.set('category', null);
this.set('subcategory', null);
},
});
Which is evaluated in:
// controllers/filter-categories.js
import Ember from 'ember';
export default Ember.Controller.extend({
userSelections: Ember.inject.service('user-selections'),
init() {
this._super(...arguments);
this.get('userSelections'); // We need to get it so that we can observe it?
// We can not declare the observers, because we need to make sure userSelections is first read
this.addObserver('userSelections.category', function() {
Ember.run.once(this, 'refreshProducts');
});
this.addObserver('userSelections.subcategory', function() {
Ember.run.once(this, 'refreshProducts');
});
},
actions: {
changedCategory: function(selectedCategory) {
this.set('selectedCategory', selectedCategory);
this.get('userSelections').set('category', selectedCategory.value);
},
changedSubcategory: function(selectedSubcategory) {
this.set('selectedSubcategory', selectedSubcategory);
this.get('userSelections').set('subcategory', selectedSubcategory.value);
},
},
refreshProducts: function() {
var userSelections = this.get('userSelections'),
category = userSelections.get('category'),
subcategory = userSelections.get('subcategory');
var products = this.store.filter('product', function(product) {
var catId = parseInt(product.get('category').get('id')),
subcatId = parseInt(product.get('subcategory').get('id'));
if (category && catId !== category) {
return false;
}
if (subcategory && subcatId !== subcategory) {
return false;
}
return true;
});
this.set('model', products);
},
});
Observing the userSelections (after some hacking, as seen in the comments) works: the actions are properly triggering the refreshProducts method. But it seems the method is not triggered when coming from the application route, probably because the controllers/filter-categories is not yet initialized.
(*) According to the documentation there are lots "issues" observing services.
Observers and asynchrony
Observers and object initialization
Unconsumed Computed Properties Do Not Trigger Observers
"The injected property is lazy; the service will not be instantiated until the property is explicitly called" (link)
As a result, code needs to be written in a difficult to understand way.
Is there a better pattern to share data between routes / controllers than using a service?
EDIT
These are my templates:
// partials/categories.hbs (used on the application.hbs template)
{{#each model.categories as |category| }}
<div class="categories-list row">
<div class="container">
<h3 class="category-name centered">
<span class="bg-left"></span>
<span class="bg-center uppercase">{{category.name}}</span>
<span class="bg-right"></span></h3>
</div>
<div class="category owl-carousel">
{{#each category.subcategories as |subcategory| }}
<div class="category-item">
<a href="{{subcategory.link}}">
<div class="category-icon">
<img src="{{subcategory.image}}">
</div>
<h4 class="capitalize" {{action "openSubcategory" category.id subcategory.id}}>{{subcategory.name}}</h4>
</a>
</div>
{{/each}}
</div>
</div>
{{/each}}
And:
// filter-categories.hbs
<div class="container">
<div class="row">
<div class="col-md-12">
<h2>Our Vault</h2>
<legend>Filter products by category / subcategory</legend>
</div>
</div>
<div class="row">
<div class="col-md-12">
<form class="form-inline portfolio-form">
<div class="form-group col-md-2">
{{#power-select options=optionsCategory selected=selectedCategory onchange=(action "changedCategory") as |category|}}
{{category.text}}
{{/power-select}}
</div>
<div class="form-group col-md-2">
{{#power-select options=optionsSubcategory selected=selectedSubcategory onchange=(action "changedSubcategory") as |subcategory|}}
{{subcategory.text}}
{{/power-select}}
</div>
<div class="form-group col-md-2">
<button type="button" class="btn btn-default" {{action "clearSelections" id}}><i class="fa fa-remove"></i> Clear Filters</button>
</div>
</form>
</div>
</div>
<div class="row">
{{partial "products"}}
</div>
</div>
Is there a reason you're avoiding the use of dynamic segments? If not you can pass the category and subcategory as dynamic segments when using transitionTo('filter-categories'), an added benefit would be that this route will become linkable :)
So for eg. you should define your filter-categories route like this:
// router.js
...
this.route('filter-categories', { path: 'filter-categories/:category_id/:subcategory_id' });
...
Now in your routes/filter-categories.js router you could do:
// routes/filter-categories
import Ember from 'ember';
export default Ember.Route.extend({
model(params) {
// you can put your `refreshProducts` logic in here
// (I mean in this router not literally in this method)
// and return the products model or whatever you want
// I will just return an object with the ids for simplicity
return {
categoryId: params.category_id,
subcategoryId: params.subcategory_id
};
}
...
And now in your application route:
// routes/application.js
import Ember from 'ember';
export default Ember.Route.extend({
actions: {
openSubcategory: function(categoryId, subcategoryId) {
this.transitionTo('filter-categories', categoryId, subcategoryId);
}
}
});
edit:
If you don't always have an categoryId and subcategoryId you can use query parameters instead of dynamic segments.

How to nest polymer templates properly?

I recently started learning polymer and am trying to use iron-ajax iron-list and templates together. For some reason the values are showing blank on screen, but cards are getting created. Taking example from this question, I created two polymer-elements search-list and search card. Search card for showing data and search list for fetching data and populating a list with card. Search list is following:
<link rel="import" href="../search-card/search-card.html">
<dom-module id="search-list">
<template>
<div>
<iron-ajax id="ajax" auto url="/data.json" handle-as="json" last-response="{{data}}"></iron-ajax>
<iron-list items="[[data]]" as="item">
<div class="flex">
<template is="dom-repeat" items="{{data}}">
<search-card></search-card>
<span>Hi</span>
<span>[[item.profile]]</span>
</template>
</div>
</iron-list>
</div>
</template>
<script>
(function () {
Polymer({
is: 'search-list',
properties: {
items: {
type: Array,
notify: true,
}
},
ready: function() {
this.items = [];
}
});
})();
</script>
</dom-module>
Search-card is the follwing:
<dom-module id="search-card">
<style>
</style>
<template>
<paper-material style="margin:15px;">
<a href="[[item.profile]]">
<img width="100" height="100" src="[[item.pic]]">
</a>
<div class="">
<div>Name: <span>[[item.name]]</span></div>
<div>Location: <span>[[item.location]]</span></div>
<div>Email: <span>[[item.email]]</span></div>
</div>
</paper-material>
</template>
<script>
(function () {
Polymer({
is: 'search-card',
properties: {
item: {
type: Object,
notify: true,
}
},
ready: function() {
this.item = {}
}
});
})();
</script>
</dom-module>
All the span fields consisting of item data are showing blank. What am I doing wrong ? How to fix it ?
For a start, you have to put the contents of the iron-list element within a template.
<iron-list items="[[data]]" as="item">
<template>
<div class="flex">
<template is="dom-repeat" items="{{data}}">
<search-card></search-card>
<span>Hi</span>
<span>[[item.profile]]</span>
</template>
</div>
</template>
</iron-list>

How do I access component properties in a transcluded view in ember?

I am passing some html to a components in ember. The html is yielded.
But the yielded html is unable to access properties defined in the component. However the properties do work on the component template.
component
import Ember from 'ember';
export default Ember.Component.extend({
user: undefined,
replyText: undefined,
onInitialization: function(){
this.set('replyText', '#' + this.user.get('username') + ' ');
}.on("init"),
remainingTweetChars: function () {
var length = 140 - this.get('replyText').length;
return length;
}.property('replyText')
});
component template
{{remainingTweetChars}} {{!-- this works --}}
{{yield}}
component usage with html which is yielded into the component template above
{{#action-reply class="item-actionables__reply"
user=user
}}
<span>{{remainingTweetChars}}</span> {{!-- this does NOT works --}}
<span>{{view.remainingTweetChars}}</span> {{!-- this does NOT works --}}
{{/action-reply}}
To overcome this you can assign a viewName to the component and use it to reference any property defined.
Example,
http://emberjs.jsbin.com/bihuzupogi/1/edit?html,js,output
hbs
<script type="text/x-handlebars">
<h2>Welcome to Ember.js</h2>
<h3>Component in block form example accessing props</h3>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
{{#test-comp propInTmpl="test-prop-in-tmpl" viewName="the-test-comp"}}
<span style="color:gray">
this is content of the block content <b>without</b> using <b>viewName</b>
(<b>props:</b> {{propInTmpl}}, {{propInClass}})
</span>
<br/>
<span style="color:gray">
this is content of the block content using the <b>viewName</b>
(<b>props:</b> {{view.the-test-comp.propInTmpl}}, {{view.the-test-comp.propInClass}})
</span>
{{/test-comp}}
</script>
<script type="text/x-handlebars" data-template-name="components/test-comp">
<i>This is content of test-compo component template! (<b>props:</b> {{propInTmpl}}, {{propInClass}})</i>
<br/>
{{yield}}
</script>
js
App = Ember.Application.create();
App.TestCompComponent = Em.Component.extend({
propInClass:"test-prop-in-class"
});