marko-js / marko

A declarative, HTML-based language that makes building web apps fun
https://markojs.com/
MIT License
13.35k stars 643 forks source link

Making the top-level page a component causes <style> tags to be stripped in the browser #810

Closed meain closed 4 years ago

meain commented 7 years ago

Bug Report

Context

When I try to do this.state.message = event.target.value inside a function which is being called on keyup it resets the css as well as the content in the input box. Code is given in Additional info section.

Expected Behavior

Don't reset CSS or remove the content inside the textbox.

Actual Behavior

No more css rules are being applied, the value inside the textbox is lost.

Additional Info ### Your Environment * Version used: 4.2.4 * Environment name and version (e.g. Chrome 39, node.js 5.4): Firefox 55, node 8.2.1, Chrome 60.0 * Operating System and version (desktop or mobile): 64bit Mac OS X 10.12.5 * Source: ```js class { onCreate(){ this.state = { message:'Hey!' } } inputChnaged(event){ console.log(event.target.value) this.state.message = event.target.value } } style { .cont { font-family: monaco; } } $ var content = 'Enter to be mirrored.' html head title -- Marko body div.cont -- ${content} input on-keyup('inputChnaged') button -- ${state.message} ```
austinkelleher commented 7 years ago

@meain This is actually related to #804. When doing a re-render of the top-level component, and diffing the <head> and <body>, you will lose content added by the module bundler. As @mlrawlings, suggested in the other thread, React has the same issue. Check out this article: https://medium.com/@dan_abramov/two-weird-tricks-that-fix-react-7cf9bbdef375

If you move the content you have in the body into another component, and only re-render that component on state change, you should see this issue go away.

meain commented 7 years ago

index.marko

<!doctype html>
html
    head
        title -- Marko
    body
      mirror

mirror.marko

class {
  onCreate(){
    this.state = {
      message:'Hey!'
    }
  }
  inputChnaged(event){
    <!-- Tottaly fine -->
    console.log(event.target.value) 
    <!-- Resets css and the value inside textbox -->
    this.state.message = event.target.value
  }
}

style {
  .cont {
    font-family: monaco;
  }
}

$ var content = 'Enter to be mirrored.'
div
    div.cont -- ${content}
    input on-keyup('inputChnaged')
    button -- ${state.message}

Created a component like this and imported into the body, the css stays, but the textfield is still being reset @austinkelleher

austinkelleher commented 7 years ago

@meain On re-render, your input will go back to it's original state, which does not have a value. You can add a no-update attribute to ensure that the value is preserved. http://markojs.com/docs/components/#codeno-updatecode

mirror.marko

class {
  onCreate(){
    this.state = {
      message:'Hey!'
    }
  }
  inputChnaged(event){
    <!-- Tottaly fine -->
    console.log(event.target.value) 
    <!-- Resets css and the value inside textbox -->
    this.state.message = event.target.value
  }
}

style {
  .cont {
    font-family: monaco;
  }
}

$ var content = 'Enter to be mirrored.'
div
    div.cont -- ${content}
    input no-update on-keyup('inputChnaged')
    button -- ${state.message}
meain commented 7 years ago

Thank you. Closing this as #804 already exists

austinkelleher commented 7 years ago

Alternatively, if you actually want the input value to be in sync with the state, you can set the value attribute on the input field:

input value=state.message on-keyup('inputChnaged')
meain commented 7 years ago

That does not bind it two way though, right? @austinkelleher

austinkelleher commented 7 years ago

@meain This is actually something we are talking about supporting If you have any thoughts, feel free to post them in these threads. We'd love to get some feedback.

https://github.com/marko-js/marko/issues/676 https://github.com/marko-js/marko/issues/528

cameronbraid commented 6 years ago

Please make marko fail fast when the user creates a full page component.

makinde commented 5 years ago

For those who find this in the future...the specific issue is that your top level page (where the <head> and <body> are located) canNOT have a class attached to it. It can have styles, but not a JS class. Took me a while to understand/figure this out.

tigt commented 4 years ago

Is this fixed now that #1428 has shipped?

DylanPiercey commented 4 years ago

@tigt yeup, good catch.