1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use leptos_dom::IntoView;
use leptos_macro::component;
use std::hash::Hash;

/// Iterates over children and displays them, keyed by the `key` function given.
///
/// This is much more efficient than naively iterating over nodes with `.iter().map(|n| view! { ... })...`,
/// as it avoids re-creating DOM nodes that are not being changed.
///
/// ```
/// # use leptos::*;
///
/// #[derive(Copy, Clone, Debug, PartialEq, Eq)]
/// struct Counter {
///   id: usize,
///   count: RwSignal<i32>
/// }
///
/// #[component]
/// fn Counters() -> impl IntoView {
///   let (counters, set_counters) = create_signal::<Vec<Counter>>(vec![]);
///
///   view! {
///     <div>
///       <For
///         // a function that returns the items we're iterating over; a signal is fine
///         each=move || counters.get()
///         // a unique key for each item
///         key=|counter| counter.id
///         // renders each item to a view
///         children=move |counter: Counter| {
///           view! {
///             <button>"Value: " {move || counter.count.get()}</button>
///           }
///         }
///       />
///       <For
///         // a function that returns the items we're iterating over; a signal is fine
///         each=move || counters.get()
///         // a unique key for each item
///         key=|counter| counter.id
///         // renders each item to a view
///         children=move |counter: Counter| {
///           view! {
///             <button>"Value: " {move || counter.count.get()}</button>
///           }
///         }
///       />
///     </div>
///   }
/// }
/// ```
#[cfg_attr(
    any(debug_assertions, feature = "ssr"),
    tracing::instrument(level = "trace", skip_all)
)]
#[component(transparent)]
pub fn For<IF, I, T, EF, N, KF, K>(
    /// Items over which the component should iterate.
    each: IF,
    /// A key function that will be applied to each item.
    key: KF,
    /// A function that takes the item, and returns the view that will be displayed for each item.
    ///
    /// ## Syntax
    /// This can be passed directly in the `view` children of the `<For/>` by using the
    /// `let:` syntax to specify the name for the data variable passed in the argument.
    ///
    /// ```rust
    /// # use leptos::*;
    /// # if false {
    /// let (data, set_data) = create_signal(vec![0, 1, 2]);
    /// view! {
    ///     <For
    ///         each=move || data.get()
    ///         key=|n| *n
    ///         // stores the item in each row in a variable named `data`
    ///         let:data
    ///     >
    ///         <p>{data}</p>
    ///     </For>
    /// }
    /// # ;
    /// # }
    /// ```
    /// is the same as
    ///  ```rust
    /// # use leptos::*;
    /// # if false {
    /// let (data, set_data) = create_signal(vec![0, 1, 2]);
    /// view! {
    ///     <For
    ///         each=move || data.get()
    ///         key=|n| *n
    ///         children=|data| view! { <p>{data}</p> }
    ///     />
    /// }
    /// # ;
    /// # }
    /// ```
    children: EF,
) -> impl IntoView
where
    IF: Fn() -> I + 'static,
    I: IntoIterator<Item = T>,
    EF: Fn(T) -> N + 'static,
    N: IntoView + 'static,
    KF: Fn(&T) -> K + 'static,
    K: Eq + Hash + 'static,
    T: 'static,
{
    leptos_dom::Each::new(each, key, children).into_view()
}