dioxus icon indicating copy to clipboard operation
dioxus copied to clipboard

table render error

Open ys2rice2yangsong opened this issue 2 years ago • 15 comments

Problem

Steps To Reproduce

Steps to reproduce the behavior:

  • When I tried to render a table list data, only the first column was displayed, and every subsequent column was lost

Expected behavior

A clear and concise description of what you expected to happen.

Screenshots

If applicable, add screenshots to help explain your problem.

Environment:

  • Dioxus version: [e.g. v0.4.0, master]
  • Rust version: [e.g. 1.72.0, nightly]
  • OS info: [e.g. MacOS]
  • App platform: [e.g. web]

Questionnaire

  • [ ] I'm interested in fixing this myself but don't know where to start
  • [ ] I would like to fix and I have a solution
  • [ ] I don't have time to fix this right now, but maybe later

ys2rice2yangsong avatar Dec 12 '23 00:12 ys2rice2yangsong

Uploading table.zip…

ys2rice2yangsong avatar Dec 12 '23 00:12 ys2rice2yangsong

Can you fill out the rest of the issue template (especially the platform and renderer you are using) and provide the code that causes an error rendering tables? The information in the template helps us reproduce and fix the issue.

ealmloff avatar Dec 12 '23 00:12 ealmloff

I have uploaded the entire project engineering

ys2rice2yangsong avatar Dec 12 '23 00:12 ys2rice2yangsong

The entire project is as follows: Uploading table.zip…

ys2rice2yangsong avatar Dec 12 '23 00:12 ys2rice2yangsong

The entire project is as follows: [Uploading table.zip…](https://github.com/DioxusLabs/dioxus/issues/1712)

I think something may have gone wrong when you tried to create a link. That link leads to the current issue

ealmloff avatar Dec 12 '23 01:12 ealmloff

Uploading table.zip…

ys2rice2yangsong avatar Dec 12 '23 01:12 ys2rice2yangsong

directory structure : 目录结构 /Cargo.toml:

[package]
name = "table"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
dioxus = "0.4.3"
dioxus-web = "0.4.3"
dioxus_table ={ path = "./dioxus-table"}

/src/hotel.rs:

use dioxus::prelude::*;
use dioxus_table::*;
#[derive(TableData, Debug)]
#[table(tag = "table")]
pub struct Hotel {
    #[table(title="标题a")]
    pub a: String,
    #[table(title="标题b")]
    pub b: String
}

/src/main.rs:

pub mod hotel;
use dioxus::prelude::*;
use hotel::{Hotel, Table};
fn main() {
    dioxus_web::launch(App)
}




fn App(cx: Scope) -> Element {
    let state = use_state(cx, ||initHotel());
    render!{
        rsx!{
            div {
                "主键"
                Table{
                    items: state.get()
                }
            }
        }
    }
}

fn initHotel() -> Vec<Hotel> {
     vec![
        Hotel{
            a: "这是A1".to_string(),
            b: "这还是B1呢".to_string()
        },
        Hotel{
            a: "a2这是".to_string(),
            b: "b2呢这还是".to_string()
        }
    ]
}

ys2rice2yangsong avatar Dec 12 '23 01:12 ys2rice2yangsong

/table-macro/Cargo.toml:

[package]
name = "table_macro"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
proc-macro = true

[dependencies]
darling = "0.20.3"
heck = "0.4.1"
proc-macro2 = "1.0.70"
quote = "1.0.33"
syn = { version = "2.0.39", features = ["full" , "extra-traits"] }

/table-macro/src/lib.rs:

mod table;
use darling::FromDeriveInput;
use proc_macro::TokenStream;
use quote::quote;
use syn::parse_macro_input;

#[proc_macro_derive(TableData, attributes(table))]
pub fn derive(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as syn::DeriveInput);

    let data = table::TableDataDeriveInput::from_derive_input(&&input).expect("结构解析错误");

    let data = quote!(#data);
    data.into()
}

ys2rice2yangsong avatar Dec 12 '23 02:12 ys2rice2yangsong

/table-macro/table.rs: use darling::{FromDeriveInput, util::{IdentString, self}, ast, FromField}; use heck::ToTitleCase; use quote::{ToTokens, quote}; use syn::spanned::Spanned;

#[derive(FromDeriveInput,Debug)] #[darling( attributes(table), supports(struct_named), forward_attrs(allow, doc, cfg) )] pub struct TableDataDeriveInput{ ident: syn::Ident, data: ast::Data<util::Ignored, TableDataField>,

#[darling(default)]
tag: Option<IdentString>,

#[darling(default)]
row: Option<IdentString>,

}

impl ToTokens for TableDataDeriveInput { fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {

    let TableDataDeriveInput {
        ident,
        tag,
        data,
        row
    } = self;

    let fields = data.as_ref().take_struct().expect("解析字段错误").fields;

    let row_render = row.as_ref().map(|d| d.as_ident().clone())
    .unwrap_or_else(||{
        syn::Ident::new("Row", row.span())
    });

    let tag = tag.as_ref().map(|tag| {
        let t = tag.as_ident();
        quote!(
            #t
        )
    }).unwrap_or( 
        quote!(table)
    );

    let mut titles = vec![];
    let mut cells = vec![];

    for field in fields.iter(){
        let cell_rendel = field.cell.as_ref().map(|render| render.as_ident().clone())
        .unwrap_or_else(|| {
            syn::Ident::new("Cell", field.cell.span())
        });
        let name = field.ident.as_ref().expect("字段解析cuowu");
        let name_str = name.to_string();

        let title = if let Some(title) = &field.title {
            title.clone()
        } else {
            name.to_string().to_title_case()
        };
        let title_render = field.title_render.as_ref().map(|head_render| head_render.as_ident().clone())
        .unwrap_or_else(|| {
            syn::Ident::new("title_render", field.title_render.span())
        });
        titles.push(quote!(
            rsx!{
                #title_render{
                    title: #title.clone()
                }
            }
        ));
        cells.push(quote!(
            rsx!{
                #cell_rendel{
                    value: #name_str.clone()
                }
            }
        ));
    }
    

    tokens.extend(quote!(

        

        

        #[inline_props]
        pub fn Table<'a>(cx: Scope<'a>, items: &'a Vec<#ident>) -> Element {
            cx.render(
                rsx!{
                    #tag {
                        tr {
                            #(#titles)*
                        }
                        items.iter().map(|item| {
                            rsx!{
                                Row{
                                    item: item,
                                    #(#titles)*
                                }
                            }
                        })
                    }
                }
            )
        }
    ))
}

}

#[derive(Debug, FromField)] #[darling(attributes(table))] struct TableDataField{ ident: Optionsyn::Ident,

#[darling(default)]
cell: Option<IdentString>,

#[darling(default)]
title: Option<String>,

#[darling(default)]
title_render:Option<IdentString>,

}

ys2rice2yangsong avatar Dec 12 '23 02:12 ys2rice2yangsong

/dioxus-table/Cargo.toml: [package] name = "dioxus_table" version = "0.1.0" edition = "2021"

See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies] dioxus = "0.4.3" gloo = "0.11.0" table_macro ={ path = "../table-macro"}

/dioxus-table/src/lib.rs: pub mod row;

pub mod cell_render;

pub mod head;

pub use row::; pub use cell_render::;

pub use table_macro::*;

pub use head::*;

/dioxus-table/src/row.rs: use dioxus::prelude::*;

#[derive(Props)] pub struct RowProps<'a, T:'a> { pub item:&'a T, pub children: Element<'a> }

pub fn Row<'a, T>(cx: Scope<'a, RowProps<'a, T>>) -> Element<'a> { cx.render( rsx!{ tr {

            cx.props.children.iter().map(|child| rsx!{child})
        }
    }
)

}

/dioxus-table/src/head.rs: use dioxus::prelude::*; use std::fmt::Display; use gloo::console::console;

#[inline_props] pub fn title_render<T:PartialEq + Display>(cx: Scope, title:T) -> Element { console!("这是打印标题".to_string()); cx.render( rsx!{ th { "{title}" } } ) }

ys2rice2yangsong avatar Dec 12 '23 02:12 ys2rice2yangsong

/dioxus-table/src/cell_render.rs: use dioxus::prelude::*; use std::fmt::Display;

#[inline_props] pub fn Cell<T:PartialEq + Display>(cx: Scope, value:T) -> Element { cx.render( rsx!{ td { "{value}" } } ) }

ys2rice2yangsong avatar Dec 12 '23 02:12 ys2rice2yangsong

What is the reason for this problem?

ys2rice2yangsong avatar Dec 12 '23 23:12 ys2rice2yangsong

What is the reason for this problem?

Can you provide a minimal example for this bug? The example should be one crate without any proc macros and preferably one file. I'm not trying to be difficult, but you understand the code that you uploaded better than me. If the issue is with rendering tables, you will be able to reproduce this with just a single component much quicker than me. This article does a pretty good job of explaining what MREs are and why they are useful https://antfu.me/posts/why-reproductions-are-required

If you think this issue is a problem with the macro code you copy-pasted into this issue, there are also places you can get help with that code: you could open a discussion asking for help or the post a message in the help channel of the Dioxus discord

ealmloff avatar Dec 12 '23 23:12 ealmloff

I have uploaded the code to the warehouse: “https://gitee.com/y-s-b/dioxus-table-macro.git” Run dx serve to see, that all headers can be displayed, and only the first column is displayed in the content area

ys2rice2yangsong avatar Dec 13 '23 00:12 ys2rice2yangsong

Dear technical experts, thank you for your hard work. When can this bug be fixed?

ys2rice2yangsong avatar Dec 15 '23 00:12 ys2rice2yangsong