Skip to main content

NestedChangeset

Struct NestedChangeset 

Source
pub struct NestedChangeset<P, C> {
    pub parent: Changeset<P>,
    /* private fields */
}
Expand description

A parent Changeset<P> plus its bound child collection.

Obtain one from decode_nested_urlencoded or (preferred) the NestedChangesetForm axum extractor.

Fields§

§parent: Changeset<P>

The parent changeset (values + per-field errors), reusing the existing Changeset pipeline.

Implementations§

Source§

impl<P, C: NestedChild> NestedChangeset<P, C>

Source

pub fn blank(parent: P) -> Self

Build a blank, non-validating nested changeset for the initial new (create) render, before the user has submitted anything.

Mirrors ChangesetForm::blank: it wraps parent in a valid Changeset (via Changeset::new, which records no errors — it does not run validator::Validate) with zero child rows. So is_valid() returns true, errors_for(..) is empty, rows() is empty, and into_valid() returns Ok((parent, vec![])) even when a required parent field is still empty.

Use this for the initial GET render of an empty (create) form so the blank page does not show a premature “field is required” error or aria-invalid="true" before the user has typed. For an edit render that must display existing child rows (with their persisted ids), use seeded instead — blank produces zero child rows and cannot pre-fill or preserve existing line items. Use decode_nested_urlencoded (or the NestedChangesetForm extractor) for the POST decode that validates a real submission and re-renders with inline errors.

Source

pub fn is_valid(&self) -> bool

true when the parent is valid, every non-destroyed row has no errors, and the children all parsed and validated.

Source

pub fn into_valid(self) -> Result<(P, Vec<C>), Self>

Consume the changeset, returning Ok((parent, children)) when valid or Err(self) (with all rows retained for re-render) when not.

The returned child vector contains only non-destroyed rows, in order.

§Errors

Returns Err(self) when the parent or any non-destroyed child row has validation errors, or any child failed to parse.

Source

pub fn errors_for(&self, key: &str) -> &[String]

Validation messages for key, or an empty slice.

Supports both parent field keys (delegated to Changeset::errors_for) and combined child keys of the form "{COLLECTION}[{i}].{sub}" (e.g. "items[1].quantity"). A bare "{COLLECTION}[{i}]" returns that row’s row-level (parse) errors.

Source

pub fn rows(&self) -> &[NestedRow]

The submitted child rows in compacted (ascending-index) order.

Source

pub const fn collection_name(&self) -> &'static str

The child collection name, i.e. NestedChild::COLLECTION.

Source§

impl<P, C: NestedChild + Serialize> NestedChangeset<P, C>

Edit-render seeding — pre-populate a non-validating changeset with existing persisted children.

The extra serde::Serialize bound lives on this impl block alone, so the core NestedChild trait stays serialize-free; only callers that seed an edit form need their child type to be serializable.

Source

pub fn seeded(parent: P, children: Vec<C>) -> Self

Build a non-validating, valid nested changeset that pre-renders one row per existing child, for the initial edit render of a form that already has persisted children.

Where blank produces zero child rows (for the create/new page), seeded produces exactly one NestedRow per element of children, so an edit form can display and preserve existing line items — including each child’s id as a hidden input (via RowScope::hidden_input) — before the first submit. That hidden id also makes the in-scope _destroy-on-existing-children flow usable: the row round-trips its identity so ticking Remove on a persisted child submits a real, identifiable row for the handler to delete.

Each row’s raw values are produced by serializing the child with serde_urlencoded::to_string and parsing the result back into the per-subfield map — the same string representation decode_nested_urlencoded populates from a real submission, so RowScope::value pre-fills a seeded row’s inputs identically to a re-rendered submitted row.

Like blank, this does not run validator::Validate: it wraps parent in a valid Changeset (via Changeset::new) and keeps valid_children = Some(children), so is_valid() returns true, errors_for(..) is empty, every seeded row reports no errors and is not destroyed, and into_valid() returns Ok((parent, children)). Use the POST decode path (decode_nested_urlencoded / the NestedChangesetForm extractor) to validate the actual edit submission.

Deeper reconciliation of persisted children — reordering, or deep-diffing submitted rows against the seeded set to compute per-row inserts / updates / deletes — is intentionally out of scope here (see issue #1346’s out-of-scope list) and remains a follow-up; seeded only pre-renders the existing rows so the no-JS edit + _destroy flow works.

Trait Implementations§

Source§

impl<P: Debug, C: Debug> Debug for NestedChangeset<P, C>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<P, C> Freeze for NestedChangeset<P, C>
where P: Freeze,

§

impl<P, C> RefUnwindSafe for NestedChangeset<P, C>

§

impl<P, C> Send for NestedChangeset<P, C>
where P: Send, C: Send,

§

impl<P, C> Sync for NestedChangeset<P, C>
where P: Sync, C: Sync,

§

impl<P, C> Unpin for NestedChangeset<P, C>
where P: Unpin, C: Unpin,

§

impl<P, C> UnsafeUnpin for NestedChangeset<P, C>
where P: UnsafeUnpin,

§

impl<P, C> UnwindSafe for NestedChangeset<P, C>
where P: UnwindSafe, C: UnwindSafe,

Blanket Implementations§

Source§

impl<T> AggregateExpressionMethods for T

Source§

fn aggregate_distinct(self) -> Self::Output
where Self: DistinctDsl,

DISTINCT modifier for aggregate functions Read more
Source§

fn aggregate_all(self) -> Self::Output
where Self: AllDsl,

ALL modifier for aggregate functions Read more
Source§

fn aggregate_filter<P>(self, f: P) -> Self::Output
where P: AsExpression<Bool>, Self: FilterDsl<<P as AsExpression<Bool>>::Expression>,

Add an aggregate function filter Read more
Source§

fn aggregate_order<O>(self, o: O) -> Self::Output
where Self: OrderAggregateDsl<O>,

Add an aggregate function order Read more
Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> AutumnDependents for T
where T: ?Sized,

Source§

fn dependents() -> &'static [RuntimeDependentSpec]

The model’s dependent-cascade specs, in declaration order. Defaults to none; #[model] overrides via an inherent shadow when dependents exist.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Converts Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Converts &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Converts &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSend for T
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_sync(self: Box<T>) -> Box<dyn Any + Sync + Send>

Converts Box<Trait> (where Trait: DowncastSync) to Box<dyn Any + Send + Sync>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Converts Arc<Trait> (where Trait: DowncastSync) to Arc<Any>, which can then be downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoSql for T

Source§

fn into_sql<T>(self) -> Self::Expression

Convert self to an expression for Diesel’s query builder. Read more
Source§

fn as_sql<'a, T>(&'a self) -> <&'a Self as AsExpression<T>>::Expression
where &'a Self: AsExpression<T>, T: SqlType + TypedExpressionType,

Convert &self to an expression for Diesel’s query builder. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T, Conn> RunQueryDsl<Conn> for T

Source§

fn execute<'conn, 'query>( self, conn: &'conn mut Conn, ) -> <Conn as AsyncConnectionCore>::ExecuteFuture<'conn, 'query>
where Conn: AsyncConnectionCore + Send, Self: ExecuteDsl<Conn> + 'query,

Executes the given command, returning the number of rows affected. Read more
Source§

fn load<'query, 'conn, U>( self, conn: &'conn mut Conn, ) -> AndThen<Self::LoadFuture<'conn>, TryCollect<Self::Stream<'conn>, Vec<U>>>
where U: Send, Conn: AsyncConnectionCore, Self: LoadQuery<'query, Conn, U> + 'query,

Executes the given query, returning a Vec with the returned rows. Read more
Source§

fn load_stream<'conn, 'query, U>( self, conn: &'conn mut Conn, ) -> Self::LoadFuture<'conn>
where Conn: AsyncConnectionCore, U: 'conn, Self: LoadQuery<'query, Conn, U> + 'query,

Executes the given query, returning a [Stream] with the returned rows. Read more
Source§

fn get_result<'query, 'conn, U>( self, conn: &'conn mut Conn, ) -> AndThen<Self::LoadFuture<'conn>, LoadNext<Pin<Box<Self::Stream<'conn>>>>>
where U: Send + 'conn, Conn: AsyncConnectionCore, Self: LoadQuery<'query, Conn, U> + 'query,

Runs the command, and returns the affected row. Read more
Source§

fn get_results<'query, 'conn, U>( self, conn: &'conn mut Conn, ) -> AndThen<Self::LoadFuture<'conn>, TryCollect<Self::Stream<'conn>, Vec<U>>>
where U: Send, Conn: AsyncConnectionCore, Self: LoadQuery<'query, Conn, U> + 'query,

Runs the command, returning an Vec with the affected rows. Read more
Source§

fn first<'query, 'conn, U>( self, conn: &'conn mut Conn, ) -> AndThen<<Self::Output as LoadQuery<'query, Conn, U>>::LoadFuture<'conn>, LoadNext<Pin<Box<<Self::Output as LoadQuery<'query, Conn, U>>::Stream<'conn>>>>>
where U: Send + 'conn, Conn: AsyncConnectionCore, Self: LimitDsl, Self::Output: LoadQuery<'query, Conn, U> + Send + 'query,

Attempts to load a single record. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Scoped for T
where T: Send + Sync + 'static,

Source§

fn scope(ctx: &PolicyContext) -> ScopeQuery<'_, Self>

Open a deferred ScopeQuery for this type. Resolves the registered scope at .load() time, not here.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WindowExpressionMethods for T

Source§

fn over(self) -> Self::Output
where Self: OverDsl,

Turn a function call into a window function call Read more
Source§

fn window_filter<P>(self, f: P) -> Self::Output
where P: AsExpression<Bool>, Self: FilterDsl<<P as AsExpression<Bool>>::Expression>,

Add a filter to the current window function Read more
Source§

fn partition_by<E>(self, expr: E) -> Self::Output
where Self: PartitionByDsl<E>,

Add a partition clause to the current window function Read more
Source§

fn window_order<E>(self, expr: E) -> Self::Output
where Self: OrderWindowDsl<E>,

Add a order clause to the current window function Read more
Source§

fn frame_by<E>(self, expr: E) -> Self::Output
where Self: FrameDsl<E>,

Add a frame clause to the current window function Read more
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more