I would like to pass data from the todos component to the todo component and display all elements in the form of a list.
I download data from the service and place it in the todos.controller. In todos.component, I use bindings: {todos: '<'}. In the todos.html view, it provides data in the form of todos = $ ctrl.todos. In todo.html, it iterates over todos and wants to return todo.name. Effect: returns only 'Todo'.
todo.service.js
export class TodoService {
constructor($http) {
'ngInject';
this.$http = $http;
}
getTodos() {
return this.$http.get('/api/todos');
}
}
todos.controller.js
class TodosController {
constructor(TodoService) {
'ngInject'
this.TodoService = TodoService;
}
$onInit() {
this.todos = null;
this.TodoService.getTodos().then(response =>
{
this.todos = response.data;
console.log(this.todos);
});
}
}
export default TodosController;
todo.component.js
import template from './todo.html';
import controller from './todo.controller';
import './todo.scss';
let todoComponent = {
bindings: {
todos: '<'
},
template,
controller
};`
export default todoComponent;
todos.html
<h1>Todos</h1>
<ul>
<todo todos="$ctrl.todos"></todo>
</ul>
todo.html
<div>
<p ng-repeat='todo in $ctrl.todos track by $index'>Todo:
{{$ctrl.todo.name}}
</p>
</div>
Change todo.html as follows:
<div>
<p ng-repeat='todo in $ctrl.todos'>Todo:
̶{̶{̶$̶c̶t̶r̶l̶.̶t̶o̶d̶o̶.̶n̶a̶m̶e̶}̶}̶
{{todo.name}}
</p>
</div>
Also with todos.html:
<h1>Todos</h1>
̶<̶u̶l̶>̶
<todo todos="$ctrl.todos"></todo>
̶<̶/̶u̶l̶>̶
The only permitted content of <ul> elements is zero or more <li> elements.
For more information, see
MDN HTML Reference - <ul> element
Related
Thanks for taking the time to read this. I have been at this now for a few hours and nearly got it right except now, Im Getting a "TypeError: render is not a function" Error and Can not figure it out, using Context API and Reactjs Please help
I have changed around States and props and back again this is the closest I got it to work
this is my parent file where I pass the UserProvider
import React, { Component } from "react";
import Group from "./Groups";
import JsonData from "../data/export";
import { UserProvider } from "./context/UserContext";
class GroupGrid extends Component {
render() {
// console.log(JsonData);
return (
<UserProvider value={JsonData}>
<div className='cards'>
<Group />
</div>
</UserProvider>
);
}
}
export default GroupGrid;
this is the child file
import React, { Component } from "react";
import UserContext from "../components/context/UserContext";
import { UserConsumer } from "../components/context/UserContext";
class GroupDetails extends Component {
static contextType = UserContext;
componentDidMount() {
const data = this.context;
// console.log(data); // { name: 'Tania', loggedIn: true }
}
render() {
return (
<UserConsumer>
{this.context.TransportGrid.GROUPS.map((value, index) => (
<div key={value.GROUP_ID} className='GroupDetail'>
<div className='groupRow1'>
<span className='Date_label'>Date:</span>
<span className='GroupDate'>
{value.GROUP_DATE}
</span>
<span className='Group_label'>Group No:</span>
<span className='GroupID'>{value.GROUP_ID}</span>
</div>
<div className='groupRow2'>
<span className='Driver_label'>Driver:</span>
<span className='DriverName'>
{value.DRIVER_NAME}
</span>
<span className='Reg_label'>Artic:</span>
<span className='VehcileReg'>
{value.VEHICLE_REG}
</span>
</div>
</div>
))}
</UserConsumer>
);
}
}
export default GroupDetails;
and this an example of the JSON it looking at
{
"TransportGrid": {
"GROUPS": [
{
"GROUP_ID": "1234",
"GROUP_DATE": "20/08/2019",
"DRIVER_ID": "22",
"DRIVER_NAME": "JIMMY BLOGGS",
"VEHICLE_REG": "XSRFDFDDF",
"START_COUNTRY": "COUNTRY1",
"END_COUNTRY": "COUNRTY2",
"MOVEMENTS": [
{
this is repeated like 180 times ANyone got any idea's?
Thanks in Advance
Problem is that your consumer from context API needs to just have a single children element as a function whereas you are having an array of JSX elements as children.
Also since you are using the latest context API you don't need to use the Consumer component, you could simply write your code as
class GroupDetails extends Component {
static contextType = UserContext;
componentDidMount() {
const data = this.context;
// console.log(data); // { name: 'Tania', loggedIn: true }
}
render() {
return (
<React.Fragment>
{this.context.TransportGrid.GROUPS.map((value, index) => (
<div key={value.GROUP_ID} className='GroupDetail'>
<div className='groupRow1'>
<span className='Date_label'>Date:</span>
<span className='GroupDate'>
{value.GROUP_DATE}
</span>
<span className='Group_label'>Group No:</span>
<span className='GroupID'>{value.GROUP_ID}</span>
</div>
<div className='groupRow2'>
<span className='Driver_label'>Driver:</span>
<span className='DriverName'>
{value.DRIVER_NAME}
</span>
<span className='Reg_label'>Artic:</span>
<span className='VehcileReg'>
{value.VEHICLE_REG}
</span>
</div>
</div>
))}
</React.Fragment>
);
}
}
export default GroupDetails;
I'd like to render new component in vue.js as if it's new page.
I'm trying to do it with something called "dynamic component"
parent: Post.vue
child: Detail.vue
so, if one of the posts is clicked, Post is off and Detail is on.
The thing is I have to send clicked post's id to the Detail.
Here's some of my code.
Post.vue
<template>
<div>
<div v-if="loading">
loading...
</div>
<div v-else class="container">
<ul>
<li v-for="(post, index) in filteredPosts" v-bind:key="post.no">
<section class="post__main">
<div #click..?? class="main__title">{{post.title}}</div>
</section>
</li>
</ul>
</div>
</div>
</template>
<script>
created() {
axios.get(this.url, {
params: {
page: this.page,
ord: this.ord,
category: []
}
}).then(res => {
this.posts = res.data.list;
this.loading = false;
this.page++;
});
Detail.vue
<template>
<div>
{{contents}}
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'Datail',
data() {
return {
req_no: null,
contents: {}
}
},
created() {
axios.get(url, {
params: {
req_no: this.req_no
}
}).then(res => {
this.contents = this.res.data
});
}
}
</script>
I feel like I can do it with props and v-if.
Can someone help me? Thanks!
Once a post is clicked, pass post id to the click handler. In the click handler, route to detail.vue passing post id as route param.
like below:
<li v-for="(post, index) in filteredPosts" v-bind:key="post.no">
<section class="post__main">
<div #click="onPostClick(post.id)" class="main__title">{{post.title}}</div>
</section>
</li>
And in your click handler:
onPostClick(id: number) {
this.$router.push({
name: 'details',
params: {
id
}
});
}
This will work provided you set up vue router correctly in your app and have a valid route for details.
You can access the post id in details component as follows:
created() {
this.postId = this.$route.params.id;
}
I would take a look at the <component> which takes a prop :to and renders a component, this is good for something like tabs where you are rendering different component from a the same general location on the page without reloading the whole page. See here:
https://v2.vuejs.org/v2/guide/components-dynamic-async.html
This seems to be a very good use case for you, just pass into the component the props you need.
I would like to show a message if there aren't objects to be returned. Something like: 'currently there are no customers available'.
I tried to tinker a bit with Object.getOwnPropertyNames() but could not get it working because the mapping function does not being called. I'm not sure where to put this check, inside the rendering function, in the with tracker or render call inside the template.
I use Meteor/react and my code looks like this:
import React, {Component} from 'react';
import {withTracker} from 'meteor/react-meteor-data';
import {Link} from 'react-router-dom';
class ArchiveCustomerOverview extends Component {
renderCustomerList() {
return this.props.users.map( user => {
return(
<div className="row" key={user._id}>
<Link to={}>
<span className="medium-1">{user.profile.name}</span>
<span className="medium-4">{user.profile.company}</span>
<span className="medium-3">{user.profile.phone}</span>
<span className="medium-3">{user.emails[0].address}</span>
</Link>
</div>
)
});
}
render() {
return (
<div>
<div className="list-overview">
<div className="list-wrapper">
<div className="list-box clear">
{this.renderCustomerList()}
</div>
</div>
</div>
</div>
);
}
}
export default withTracker( (props) => {
Meteor.subscribe('users');
return {
users: Meteor.users.find({
'profile.isArchived': 0,
'roles.customers' : 'customer'
}).fetch()
};
})(ArchiveCustomerOverview);
Just check on the number of users before you render them like this:
renderCustomerList() {
if (this.props.users.length === 0) {
return (<div>Currently there are no customers available</div>)
}
return this.props.users.map( user => {
But a word of warning: you may not get what you want from the users collection - for security reasons it is treated differently from other collections.
I need to build list of dynamical components that I can group in group component. Then I need to send all information about builded components and groups.
I can use <component v-for="componentName in myComponents" :is="componentName"></component>, and get information about components using this.$children.map(component => component.getInformation()), but then I can't move some component to group component, because I have only component name not the component instance with data (it just render with default data).
I also can use this:
<template>
<div ref="container"> </div>
</template>
<script>
import someComponent from 'someComponent.vue'
import Vue from 'vue'
export default {
data () {
return {
myComponents: []
}
},
methods: {
addSomeComponent () {
let ComponentClass = Vue.extend(someComponent);
let instance = new ComponentClass({});
myComponents.push(instance);
instance.$mount();
this.$refs.container.appendChild(instance.$el)
},
getInformation () {
return this.myComponents.map(component => component.getInformation());
}
}
}
</script>
But then I can't use reactivity, directives (e.g. directives for drag and drop), and it's not data driven pattern.
Any suggestions?
<template>
<div class="component">
<template v-for="(child, index) in children()">
<component :is="child" :key="child.name"></component>
</template>
</div>
</template>
<script>
import someComponent from 'someComponent.vue'
import Vue from 'vue'
export default {
methods: {
children() {
let ComponentClass = Vue.extend(someComponent);
let instance = new ComponentClass({});
return [
instance
];
},
}
}
</script>
How to update component when route changes. I have this component :
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute } from '#angular/router';
import { ListService } from '../list/list.service';
#Component({
selector: 'view',
template: `
<div *ngIf="!entity">
<p>Select <b (click)="showRow()">row {{entity}}</b>!</p>
</div>
<div *ngIf="entity">
<p >{{entity.id}}</p>
<p >{{entity.name}}</p>
<p >{{entity.weight}}</p>
<p >{{entity.symbol}}</p>
</div>
`,
styles: []
})
export class ViewComponent implements OnInit {
constructor(
private route: ActivatedRoute,
private service: ListService
) {
this.route.params.subscribe(params => {
const id = parseInt(params['id']);
if (id) {
const entity = this.service.getRow(id);
this.entity = entity
}
});
}
entity;
showRow() {
console.log(this.entity);
}
ngOnInit() {
}
}
in this.entity inside constructor i have desired object but when i execute showRow this.entity is undefined, what i'm doing wrong ? I have tried to change property to different name, and it didn't work as expected, if any one knows how to resolve this or point me to right direction.
EDIT:
getRow from service
getRow(id) {
console.log(id, 'test');
return this.datasource.find(row => row.id === id);//returns good row
}
Move your code to ngOnInit() method and check will you get value or not.
ngOnInit() {
this.route.params.subscribe(params => {
const id = parseInt(params['id']);
if (id) {
const entity = this.service.getRow(id);
this.entity = entity
}
});
}
I believe you need to define/initialize the entity that is positioned above showRow, such as:
const entity = Entity;
or something along those lines. apologies I am quite new to angular as well.
I found answer to my problem, i just needed to put router-outlet in template just like that :
....
....
template: `
<router-outlet>
<div *ngIf="row?.id; else elseBlock">
<div>
<p>{{row.id}}</p>
<p>{{row.name}}</p>
<p>{{row.weight}}</p>
<p>{{row.symbol}}</p>
</div>
</div>
</router-outlet>
`,